Skip to main content

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? where T 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 use unsafeCast() 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 ​

A backend for a simulated resource.

Initializers ​

bring sim;

new sim.Resource(factory: IResourceFactory);
NameTypeDescription
factory
IResourceFactory
No description.

factoryRequired ​

Methods ​

Preflight Methods​
NameDescription
addEnvironment
Add an environment variable to make available to the inflight code.
addPermission
Add a simulated permission to this inflight host.
createToken
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.
toSimulator
Convert this resource to a resource schema for the simulator.
Inflight Methods​
NameDescription
call
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 ​

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 ​

NameDescription
onLiftType
A hook called by the Wing compiler once for each inflight host that needs to use this type inflight.
toInflight
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 ​

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 ​

Properties ​

NameTypeDescription
node
constructs.NodeThe tree node.

nodeRequired ​
node: Node;
  • Type: constructs.Node

The tree node.


Protocols ​

IResource ​

Contract that a resource backend must implement.

Methods ​

NameDescription
onStop
Runs when the resource is stopped.

onStop ​
onStop(): void

Runs when the resource is stopped.

IResourceContext ​

Context for implementing a simulator resource.

Methods ​

NameDescription
log
Log a message at the current point in time.
resolveToken
Resolves a token value.
statedir
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 ​

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 ​

Inflight client: @winglang/sdk.sim.IResourceFactoryClient

A resource with an inflight "handle" method that can be passed to the sim.Resource constructor.

IResourceFactoryClient ​

A resource with an inflight "handle" method that can be passed to the sim.Resource constructor.

Methods ​

NameDescription
handle
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 ​

ISimulatorInflightHost ​

Interfaces shared by all preflight classes that host inflight code.

Methods ​

NameDescription
addPermission
Add a simulated permission to this inflight host.

addPermission ​
addPermission(resource: IResource, op: str): void

Add a simulated permission to this inflight host.

resourceRequired ​

The resource to add.


opRequired ​
  • Type: str

The action to add.


Properties ​

NameTypeDescription
node
constructs.NodeThe tree node.

nodeRequired ​
node: Node;
  • Type: constructs.Node

The tree node.


ISimulatorResource ​

Interfaces shared by all preflight classes targeting the simulator.

Methods ​

NameDescription
toSimulator
Convert this resource to a resource schema for the simulator.

toSimulator ​
toSimulator(): ToSimulatorOutput

Convert this resource to a resource schema for the simulator.

Properties ​

NameTypeDescription
node
constructs.NodeThe tree node.

nodeRequired ​
node: Node;
  • Type: constructs.Node

The tree node.