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.