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
callmethod 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,callwill 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:
numstrboolJsonArrayMapT?whereTis 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
fromJsonmethods. 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. |
factoryRequired
- 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.
nameRequired
- Type: str
valueRequired
- Type: str
addPermission
addPermission(resource: IResource, op: str): void
Add a simulated permission to this inflight host.
resourceRequired
- Type: IResource
opRequired
- 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.
nameRequired
- 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.
methodRequired
- Type: str
argsOptional
- 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.
hostRequired
- Type: IInflightHost
opsRequired
- 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.
objRequired
- Type: IResource
Properties
| Name | Type | Description |
|---|---|---|
| constructs.Node | The tree node. |
nodeRequired
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.
messageRequired
- Type: str
The message to log.
levelOptional
- 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.
nameRequired
- Type: str
The name of the token.
valueRequired
- 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.
contextRequired
- 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.
resourceRequired
- Type: IResource
The resource to add.
opRequired
- Type: str
The action to add.
Properties
| Name | Type | Description |
|---|---|---|
| constructs.Node | The tree node. |
nodeRequired
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. |
nodeRequired
node: Node;
- Type: constructs.Node
The tree node.