Documentation
    Preparing search index...

    Interface ObjectSharedContext<TState>

    The context that gives access to all Restate-backed operations, for example

    • sending reliable messages / RPC through Restate
    • execute non-deterministic closures and memoize their result
    • sleeps and delayed calls
    • awakeables
    • ...

    This context can be used only within a shared virtual objects.

    interface ObjectSharedContext<TState extends TypedState = UntypedState> {
        console: Console;
        date: ContextDate;
        key: string;
        rand: Rand;
        attach<T>(invocationId: InvocationId, serde?: Serde<T>): RestatePromise<T>;
        awakeable<T>(serde?: Serde<T>): { id: string; promise: RestatePromise<T> };
        cancel(invocationId: InvocationId): void;
        genericCall<
            REQ = Uint8Array<ArrayBufferLike>,
            RES = Uint8Array<ArrayBufferLike>,
        >(
            call: GenericCall<REQ, RES>,
        ): InvocationPromise<RES>;
        genericSend<REQ = Uint8Array<ArrayBufferLike>>(
            call: GenericSend<REQ>,
        ): InvocationHandle;
        get<TValue, TKey extends string | number | symbol = string>(
            name: TState extends UntypedState ? string : TKey,
            serde?: Serde<TState extends UntypedState ? TValue : TState[TKey]>,
        ): Promise<null | (TState extends UntypedState ? TValue : TState[TKey])>;
        objectClient<D>(
            opts: VirtualObjectDefinitionFrom<D>,
            key: string,
        ): Client<VirtualObject<D>>;
        objectSendClient<D>(
            obj: VirtualObjectDefinitionFrom<D>,
            key: string,
            opts?: SendOptions,
        ): SendClient<VirtualObject<D>>;
        rejectAwakeable(id: string, reason: string): void;
        request(): Request;
        resolveAwakeable<T>(id: string, payload?: T, serde?: Serde<T>): void;
        run<T>(action: RunAction<T>): RestatePromise<T>;
        run<T>(name: string, action: RunAction<T>): RestatePromise<T>;
        run<T>(
            name: string,
            action: RunAction<T>,
            options: RunOptions<T>,
        ): RestatePromise<T>;
        serviceClient<D>(opts: ServiceDefinitionFrom<D>): Client<Service<D>>;
        serviceSendClient<D>(
            service: ServiceDefinitionFrom<D>,
            opts?: SendOptions,
        ): SendClient<Service<D>>;
        sleep(duration: number | Duration, name?: string): RestatePromise<void>;
        stateKeys(): Promise<string[]>;
        workflowClient<D>(
            opts: WorkflowDefinitionFrom<D>,
            key: string,
        ): Client<Workflow<D>>;
        workflowSendClient<D>(
            opts: WorkflowDefinitionFrom<D>,
            key: string,
        ): SendClient<Workflow<D>>;
    }

    Type Parameters

    Hierarchy (View Summary)

    Index

    Properties

    console: Console

    Console to use for logging. It attaches to each log message some contextual information, such as invoked service method and invocation id, and automatically excludes logs during replay.

    Deterministic date.

    key: string
    rand: Rand

    Deterministic random methods; these are inherently predictable (seeded on the invocation ID, which is not secret) and so should not be used for any cryptographic purposes. They are useful for identifiers, idempotency keys, and for uniform sampling from a set of options. If a cryptographically secure value is needed, please generate that externally and capture the result with a side effect.

    Calls to these methods from inside ctx.run are disallowed and will fail - side effects must be idempotent, and these calls are not.

    Methods

    • Register an awakeable and pause the processing until the awakeable ID (and optional payload) have been returned to the service (via ctx.completeAwakeable(...)). The SDK deserializes the payload with JSON.parse(result.toString()) as T.

      Type Parameters

      • T

      Parameters

      Returns { id: string; promise: RestatePromise<T> }

      • id: the string ID that has to be used to complete the awakaeble by some external service
      • promise: the Promise that needs to be awaited and that is resolved with the payload that was supplied by the service which completed the awakeable
      Retryable errors and terminal errors
      const awakeable = ctx.awakeable<string>();

      // send the awakeable ID to some external service that will wake this one back up
      // The ID can be retrieved by:
      const id = awakeable.id;

      // ... send to external service ...

      // Wait for the external service to wake this service back up
      const result = await awakeable.promise;
    • Reject an awakeable. When rejecting, the service waiting on this awakeable will be woken up with a terminal error with the provided reason.

      Parameters

      • id: string

        the string ID of the awakeable. This is supplied by the service that needs to be woken up.

      • reason: string

        the reason of the rejection.

      Returns void

      // The sleeping service should have sent the awakeableIdentifier string to this service.
      ctx.rejectAwakeable(awakeableIdentifier, "super bad error");
    • Resolve an awakeable.

      Type Parameters

      • T

      Parameters

      • id: string

        the string ID of the awakeable. This is supplied by the service that needs to be woken up.

      • Optionalpayload: T

        the payload to pass to the service that is woken up. The SDK serializes the payload with Buffer.from(JSON.stringify(payload)) and deserializes it in the receiving service with JSON.parse(result.toString()) as T.

      • Optionalserde: Serde<T>

      Returns void

      Retryable error with custom retry delay
      // The sleeping service should have sent the awakeableIdentifier string to this service.
      ctx.resolveAwakeable(awakeableIdentifier, "hello");
    • Run an operation and store the result in Restate. The operation will thus not be re-run during a later replay, but take the durable result from Restate.

      This let you capture potentially non-deterministic computation and interaction with external systems in a safe way.

      Failure semantics are:

      • If an operation has run and persisted before, the result (value or Error) will be taken from the Restate journal.
      • There is a small window where an action may be re-run, if a failure occurred between a successful run and persisting the result.
      • No second action will be run while a previous run's result is not yet durable. That way, effects that build on top of each other can assume deterministic results from previous runs, and at most one run will be re-executed on replay (the latest, if the failure happened in the small windows described above).

      You can customize retry options by either:

      • Providing retry policy options in RunOptions
      • Throwing RetryableError, providing retryAfter option. This can be especially useful when interacting with HTTP requests returning the Retry-After header. You can combine the usage of throwing RetryableError with the maxRetryAttempts/maxRetryDuration from RunOptions.

      Type Parameters

      • T

      Parameters

      Returns RestatePromise<T>

      const result = await ctx.run(someExternalAction)
      
      const result = await ctx.run("my action", someExternalAction, { maxRetryAttempts: 10 })
      
      await ctx.run("payment action", async () => {
      const result = await paymentProvider.charge(txId, paymentInfo);
      if (result.paymentRejected) {
      // this action will not be retried anymore
      throw new TerminalError("Payment failed");
      } else if (result.paymentGatewayBusy) {
      // restate will retry automatically
      // to bound retries, use RunOptions
      throw new Error("Payment gateway busy");
      } else {
      // success!
      }
      });
      await ctx.run("payment action", async () => {
      const res = fetch(...);
      if (!res.ok) {
      // Read Retry-After header
      const retryAfterHeader = res.headers['Retry-After']

      // Use RetryableError to customize in how long to retry
      throw RetryableError.from(cause, { retryAfter: { seconds: retryAfterHeader } })
      }
      }, {
      // Retry at most ten times
      maxRetryAttempts: 10
      });
    • Same as run, but providing a name, used for observability purposes.

      Type Parameters

      • T

      Parameters

      Returns RestatePromise<T>

    • See run

      Type Parameters

      • T

      Parameters

      Returns RestatePromise<T>

    • Makes a type-safe request/response RPC to the specified target service.

      The RPC goes through Restate and is guaranteed to be reliably delivered. The RPC is also journaled for durable execution and will thus not be duplicated when the handler is re-invoked for retries or after suspending.

      This call will return the result produced by the target handler, or the Error, if the target handler finishes with a Terminal Error.

      This call is a suspension point: The handler might suspend while awaiting the response and resume once the response is available.

      Type Parameters

      • D

      Parameters

      Returns Client<Service<D>>

      Service Side:

      const service = restate.service(
      name: "myservice",
      handlers: {
      someAction: async(ctx: restate.Context, req: string) => { ... },
      anotherAction: async(ctx: restate.Context, count: number) => { ... }
      });

      // option 1: export only the type signature
      export type Service = typeof service;


      restate.endpoint().bind(service).listen(9080);

      Client side:

      // option 1: use only types and supply service name separately
      const result1 = await ctx.serviceClient<Service>({name: "myservice"}).someAction("hello!");

      // option 2: use full API spec
      type MyService: Service = { name: "myservice" };
      const result2 = await ctx.serviceClient(Service).anotherAction(1337);
    • Makes a type-safe one-way RPC to the specified target service. This method effectively behaves like enqueuing the message in a message queue.

      The message goes through Restate and is guaranteed to be reliably delivered. The RPC is also journaled for durable execution and will thus not be duplicated when the handler is re-invoked for retries or after suspending.

      This call will return immediately; the message sending happens asynchronously in the background. Despite that, the message is guaranteed to be sent, because the completion of the invocation that triggers the send (calls this function) happens logically after the sending. That means that any failure where the message does not reach Restate also cannot complete this invocation, and will hence recover this handler and (through the durable execution) recover the message to be sent.

      Type Parameters

      • D

      Parameters

      Returns SendClient<Service<D>>

      Service Side:

      const service = restate.service(
      name: "myservice",
      handlers: {
      someAction: async(ctx: restate.Context, req: string) => { ... },
      anotherAction: async(ctx: restate.Context, count: number) => { ... }
      });

      // option 1: export only the type signature of the router
      export type MyApi = typeof service;

      // option 2: export the API definition with type and name (name)
      const MyService: MyApi = { name: "myservice" };

      restate.endpoint().bind(service).listen(9080);

      Client side:

      // option 1: use only types and supply service name separately
      ctx.serviceSendClient<MyApi>({name: "myservice"}).someAction("hello!");

      // option 2: use full API spec
      ctx.serviceSendClient(MyService).anotherAction(1337);