Resolvers
Change resolver behavior within an environment.
Tags allow you to scope requests within an environment. Both tags and environment need to match for a resolver to be a candidate to execute.
You might consider using tags, for example, to change out
whether you want to use a sandbox environment for a vendor,
or to bypass the vendor and return constant values in a
staging
environment.
Tags can be either a string value, or a key-value pair. As a best practice (and fitting with recommendations from other services like Datadog), we recommend using key-value pairs, but the choice is yours.
There are two ways to specify tags on resolvers:
“key”
-
As a single scalar string.“key:value”
-
As a string value representing a key-value pair.Resolvers take one or many tags, all of which need to match for the resolver to run. For example, you may want to test with a sandboxed vendor, and also be able to set a constant value for a particular feature. For instructions on how to set tags on SQL file resolvers, see the SQL file resolvers docs
@online(tags=["api:mock", "fraud"])
def simulate_fraud(id: User.id) -> User.fraud_score:
return 100
@online(tags="api:mock")
def simulate_no_fraud(id: User.id) -> User.fraud_score:
return 10
@online(tags="api:sandbox")
def sandbox_score(
name: User.name,
email: User.email,
) -> User.fraud_score:
return sandbox.fraud_score(name, email).score
@online
def real_score(
name: User.name,
email: User.email,
) -> Features[User.fraud_score, User.fraud_tags]:
r = prod.fraud_score(name, email).score
return User(fraud_score=r.score, fraud_tags=r.tags)
In the above example, the resolver that is chosen to compute
the User.fraud_score
feature will depend on the tags provided
at query time. The table below shows which resolver will be
chosen for a given set of tags.
Query tags | Resolver |
---|---|
[api:mock, fraud] | simulate_fraud |
api:mock | simulate_no_fraud |
api:sandbox | sandbox_score |
<otherwise> | real_score |
Note that these resolvers don’t need to take the same set of inputs, and don’t need to return the same types.
Like Environments, tags control when resolvers run
based on the
Online Context or Training Context
matching the tags provided to the resolver decorator.
Resolvers optionally take a keyword argument named tags
that can take one of three types:
If your resolver is tagged only by a key (not a key-value pair), and the request context contains a key-value pair such that the resolver’s tag (a key only) matches they key of a key-value pair in the context, the resolver will be eligible to run. For example:
Resolver Tag | Request Context | Matches? |
---|---|---|
api | api | Yes |
api | api:live | Yes |
[api:live, mock-phone] | [api:live, mock-phone] | Yes |
[api:live, mock-phone] | api:live | No |
api:live | api | No |
api:fixture | api:live | No |
Frequently, you’ll want to combine tags and Environments,
as below.
This span uses a constant value in staging when the tag api
takes the value fixture
,
uses the sandboxed fraud vendor in staging when the tag api
takes the value live
,
and uses the production fraud vendor in production.
@online(environment="staging", tags="api:fixture")
def fraud_score_fixture(email: UserFeatures.email) -> UserFeatures.fraud_score:
if email == "elliot@chalk.ai":
return 100
return 50
@online(environment="staging", tags="api:live")
def fraud_score_sandbox(email: UserFeatures.email) -> UserFeatures.fraud_score:
return api_vendor_sandbox.fraud_score(email, profile="dev")
@online(environment="production")
def fraud_score_prod(email: UserFeatures.email) -> UserFeatures.fraud_score:
return api_vendor_live.fraud_score(email)