Resource
The sim.Resource
class models a simulated resource with a lifecycle.
It's can be used to represent any cloud service where API calls are made over HTTP
to interact with the service at runtime.
Usage
As an example, suppose we want to simulate a service that stores a number, like the one in cloud.Counter
, which has two methods: inc
and peek
.
First, we'll define an inflight class that represents the service's backend:
bring sim;
// a resource backend must implement IResource
inflight class CounterBackend impl sim.IResource {
var counter: num;
new(ctx: sim.IResourceContext) {
// startup code
this.counter = 0;
}
pub onStop() {
// shutdown code
}
pub inc(n: num?): num {
let p = this.counter;
this.counter += (n ?? 1);
return p;
}
pub peek(): num {
return this.counter;
}
}
Each CounterBackend
object that's created will have its own state.
It will be initialized by the simulator with its constructor (the new()
method), and shut down using its onStop
method.
From the perspective of CounterBackend
, its inc
and peek
methods are always called serially, even if requests are made concurrently from other resources.
Next, we have to define a preflight class which represents the service's frontend:
class Counter {
backend: sim.Resource;
new() {
// this is a "backend factory". it returns an inflight class that implements the
// resource.
let factory = inflight (ctx): sim.IResource => {
return new CounterBackend(ctx);
};
this.backend = new sim.Resource(factory);
}
pub inflight inc(n: num?): num {
let response = this.backend.call("inc", [Json (n ?? 1)]);
return num.fromJson(response);
}
pub inflight peek(): num {
let response = this.backend.call("peek");
return num.fromJson(response);
}
}
The Counter
class is a simple wrapper around the CounterBackend
class. It provides a way to interact with the resource using the inc
and peek
methods.
sim.Resource
has an inflight method named call
that takes the name of a method to call and an array of arguments, and returns the serialized response from the resource.
The arguments are serialized and sent to the resource over HTTP, which will process the request and returns a serialized response.
Note: Since the
call
method makes networked requests, it's important that the resource implementation provided by the inflight class responds in a timely manner. If the resource takes over 30 seconds to respond,call
will throw an error, and the simulator will terminate the resource.
The Counter
class can be used like this:
let c = new Counter();
new cloud.Function(inflight () => {
log("counter is {c.peek()}");
c.inc();
log("counter is now {c.peek()}");
});
Serializability
Methods that are called on a sim.Resource
instance must be serializable, meaning
all of their arguments and return values must be serializable.
The following types are serializable:
num
str
bool
Json
Array
Map
T?
whereT
is a serializable type- enums
- structs that contain only serializable types
The call
function on sim.Resource
only supports arguments that are valid Json
values.
To convert a value to Json
, use the Json
constructor:
let x: num = 5;
let y: str = "a";
this.backend.call("myMethod", Json [x, y]);
Return values can be converted back from Json
using an appropriate fromJson
method.
let response = this.backend.call("myMethod");
let result: num = num.fromJson(response);
Note: some types are missing
fromJson
methods. To work around this, you may useunsafeCast()
to cast the value into the desired type.let response = this.backend.call("myOtherMethod");
let result: MyEnum = unsafeCast(response);
Late-bound Tokens
Consider a use case where there is an attribute of a simulated service that only gets resolved during initialization (e.g. the exposed port of a container). In order to create such resources, we need a way to obtain a lazy token that gets resolved during simulator initialization.
Use the preflight method resource.createToken(key)
to obtain a token that can be used to reference the value of the attribute at runtime.
During resource simulation, you must call ctx.resolveToken(key, value)
during a resource's constructor method to set the runtime value.
inflight class MyResourceBackend impl sim.IResource {
new(ctx: sim.IResourceContext) {
ctx.resolveToken("startTime", "2023-10-16T20:47:39.511Z");
}
pub onStop() {}
}
class MyResource {
backend: sim.Resource;
pub startTime: str;
new() {
this.backend = new sim.Resource(inflight () => {
return new MyResourceBackend();
});
this.startTime = this.backend.createToken("startTime");
}
}
let r = new MyResource();
new cloud.Function(inflight () => {
let time = util.env("START_TIME");
log("start time is {time}");
}, env: {
START_TIME: r.startTime, // lazy token can be used in preflight configuration
});
// ...or you can use it directly inflight, where the value is automatically resolved
new cloud.Function(inflight () => {
log("start time is {r.startTime}");
});
API Reference
Resources
Resource
- Implements: IResource, ISimulatorResource, IInflightHost, ISimulatorInflightHost
A backend for a simulated resource.
Initializers
bring sim;
new sim.Resource(factory: IResourceFactory);
Name | Type | Description |
---|---|---|
|
| No description. |
factory
Required
- Type: IResourceFactory
Methods
Preflight Methods
Name | Description |
---|---|
| Add an environment variable to make available to the inflight code. |
| Add a simulated permission to this inflight host. |
| Obtain a token that can be used to reference an attribute of this resource that is only resolved once the resource is started in the simulator. |
| Convert this resource to a resource schema for the simulator. |
Inflight Methods
Name | Description |
---|---|
| Call a method on the resource. |
addEnvironment
addEnvironment(name: str, value: str): void
Add an environment variable to make available to the inflight code.
name
Required
- Type: str
value
Required
- Type: str
addPermission
addPermission(resource: IResource, op: str): void
Add a simulated permission to this inflight host.
resource
Required
- Type: IResource
op
Required
- Type: str
createToken
createToken(name: str): str
Obtain a token that can be used to reference an attribute of this resource that is only resolved once the resource is started in the simulator.
If the token is used in inflight code or in the configuration of a simulated resource (e.g. as an environment variable), the relevant resource will automatically take a dependency on the resource the token belongs to.
name
Required
- Type: str
The name of the token.
toSimulator
toSimulator(): ToSimulatorOutput
Convert this resource to a resource schema for the simulator.
call
inflight call(method: str, args?: MutArray<Json>): Json
Call a method on the resource.
method
Required
- Type: str
args
Optional
- Type: MutArray<Json>
Static Functions
Name | Description |
---|---|
| A hook called by the Wing compiler once for each inflight host that needs to use this type inflight. |
| Generates an asynchronous JavaScript statement which can be used to create an inflight client for a resource. |
onLiftType
bring sim;
sim.Resource.onLiftType(host: IInflightHost, ops: MutArray<str>);
A hook called by the Wing compiler once for each inflight host that needs to use this type inflight.
The list of requested inflight methods
needed by the inflight host are given by ops
.
This method is commonly used for adding permissions, environment variables, or other capabilities to the inflight host.
host
Required
- Type: IInflightHost
ops
Required
- Type: MutArray<str>
toInflight
bring sim;
sim.Resource.toInflight(obj: IResource);
Generates an asynchronous JavaScript statement which can be used to create an inflight client for a resource.
NOTE: This statement must be executed within an async context.
obj
Required
- Type: IResource
Properties
Name | Type | Description |
---|---|---|
| constructs.Node | The tree node. |
node
Required
node: Node;
- Type: constructs.Node
The tree node.
Protocols
IResource
- Implemented By: IResource
Contract that a resource backend must implement.
Methods
Name | Description |
---|---|
| Runs when the resource is stopped. |
onStop
onStop(): void
Runs when the resource is stopped.
IResourceContext
- Implemented By: IResourceContext
Context for implementing a simulator resource.
Methods
Name | Description |
---|---|
| Log a message at the current point in time. |
| Resolves a token value. |
| The directory for the resource's state. |
log
inflight log(message: str, level?: LogLevel): void
Log a message at the current point in time.
Defaults to info
level.
message
Required
- Type: str
The message to log.
level
Optional
- Type: LogLevel
The severity of the message.
resolveToken
inflight resolveToken(name: str, value: str): void
Resolves a token value.
All tokens must be resolved during the constructor of the resource.
name
Required
- Type: str
The name of the token.
value
Required
- Type: str
The value of the token.
statedir
statedir(): str
The directory for the resource's state.
IResourceFactory
-
Extends: IInflight
-
Implemented By: IResourceFactory
Inflight client: @winglang/sdk.sim.IResourceFactoryClient
A resource with an inflight "handle" method that can be passed to the sim.Resource
constructor.
IResourceFactoryClient
- Implemented By: IResourceFactoryClient
A resource with an inflight "handle" method that can be passed to the sim.Resource
constructor.
Methods
Name | Description |
---|---|
| Function that will be called to initialize the simulator resource. |
handle
inflight handle(context: IResourceContext): IResource?
Function that will be called to initialize the simulator resource.
To implement a shutdown sequence, return an object that implements the IResource
inflight interface with an onStop()
method.
context
Required
- Type: IResourceContext
ISimulatorInflightHost
-
Extends: IInflightHost
-
Implemented By: Resource, ISimulatorInflightHost
Interfaces shared by all preflight classes that host inflight code.
Methods
Name | Description |
---|---|
| Add a simulated permission to this inflight host. |
addPermission
addPermission(resource: IResource, op: str): void
Add a simulated permission to this inflight host.
resource
Required
- Type: IResource
The resource to add.
op
Required
- Type: str
The action to add.
Properties
Name | Type | Description |
---|---|---|
| constructs.Node | The tree node. |
node
Required
node: Node;
- Type: constructs.Node
The tree node.
ISimulatorResource
Interfaces shared by all preflight classes targeting the simulator.
Methods
Name | Description |
---|---|
| Convert this resource to a resource schema for the simulator. |
toSimulator
toSimulator(): ToSimulatorOutput
Convert this resource to a resource schema for the simulator.
Properties
Name | Type | Description |
---|---|---|
| constructs.Node | The tree node. |
node
Required
node: Node;
- Type: constructs.Node
The tree node.