@restatedev/restate-sdk-cloudflare-workers 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/endpoint/components.cjs +67 -10
- package/dist/endpoint/components.js +67 -10
- package/dist/endpoint/components.js.map +1 -1
- package/dist/endpoint/handlers/fetch.cjs +5 -3
- package/dist/endpoint/handlers/fetch.js +6 -4
- package/dist/endpoint/handlers/fetch.js.map +1 -1
- package/dist/endpoint/handlers/generic.cjs +7 -4
- package/dist/endpoint/handlers/generic.js +7 -4
- package/dist/endpoint/handlers/generic.js.map +1 -1
- package/dist/endpoint/handlers/lambda.cjs +6 -3
- package/dist/endpoint/handlers/lambda.js +7 -4
- package/dist/endpoint/handlers/lambda.js.map +1 -1
- package/dist/endpoint/handlers/preview.cjs +97 -0
- package/dist/endpoint/handlers/preview.js +98 -0
- package/dist/endpoint/handlers/preview.js.map +1 -0
- package/dist/endpoint/handlers/utils.cjs +26 -11
- package/dist/endpoint/handlers/utils.js +26 -12
- package/dist/endpoint/handlers/utils.js.map +1 -1
- package/dist/endpoint/node_endpoint.cjs +9 -6
- package/dist/endpoint/node_endpoint.js +9 -6
- package/dist/endpoint/node_endpoint.js.map +1 -1
- package/dist/io.cjs +7 -2
- package/dist/io.js +7 -2
- package/dist/io.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/dist/promises.cjs +4 -3
- package/dist/promises.js +4 -3
- package/dist/promises.js.map +1 -1
- package/package.json +4 -4
|
@@ -26,23 +26,37 @@ function errorResponse(code, message) {
|
|
|
26
26
|
}, new TextEncoder().encode(JSON.stringify({ message })));
|
|
27
27
|
}
|
|
28
28
|
function simpleResponse(statusCode, headers, body) {
|
|
29
|
-
return {
|
|
30
|
-
headers
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
const { done } = await inputReader.next();
|
|
35
|
-
if (done) break;
|
|
36
|
-
}
|
|
37
|
-
await outputWriter.write(body);
|
|
38
|
-
await outputWriter.close();
|
|
29
|
+
return { async process({ inputReader, outputWriter, writeHead }) {
|
|
30
|
+
writeHead(statusCode, headers);
|
|
31
|
+
while (true) {
|
|
32
|
+
const { done } = await inputReader.next();
|
|
33
|
+
if (done) break;
|
|
39
34
|
}
|
|
40
|
-
|
|
35
|
+
await outputWriter.write(body);
|
|
36
|
+
await outputWriter.close();
|
|
37
|
+
} };
|
|
41
38
|
}
|
|
42
39
|
function emptyInputReader() {
|
|
43
40
|
return (async function* () {})()[Symbol.asyncIterator]();
|
|
44
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Bundles a `writeHead` callback with a Promise that resolves once the head
|
|
44
|
+
* is committed. Used by adapters (fetch, lambda) that need to observe the
|
|
45
|
+
* head commit from outside the `process()` call.
|
|
46
|
+
*/
|
|
47
|
+
function captureHead() {
|
|
48
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
49
|
+
return {
|
|
50
|
+
writeHead: (statusCode, headers) => {
|
|
51
|
+
resolve({
|
|
52
|
+
statusCode,
|
|
53
|
+
headers: { ...headers }
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
head: promise
|
|
57
|
+
};
|
|
58
|
+
}
|
|
45
59
|
|
|
46
60
|
//#endregion
|
|
47
|
-
export { emptyInputReader, errorResponse, invocationIdFromHeaders, simpleResponse, tryCreateContextualLogger };
|
|
61
|
+
export { captureHead, emptyInputReader, errorResponse, invocationIdFromHeaders, simpleResponse, tryCreateContextualLogger };
|
|
48
62
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/endpoint/handlers/utils.ts"],"sourcesContent":["import {\n LoggerContext,\n LogSource,\n LoggerTransport,\n} from \"../../logging/logger_transport.js\";\nimport type {\n Headers,\n InputReader,\n ResponseHeaders,\n RestateResponse,\n} from \"./types.js\";\nimport { createLogger, Logger } from \"../../logging/logger.js\";\nimport { parseUrlComponents } from \"../components.js\";\nimport { X_RESTATE_SERVER } from \"../../user_agent.js\";\n\nexport function tryCreateContextualLogger(\n loggerTransport: LoggerTransport,\n url: string,\n headers: Headers,\n additionalContext?: { [name: string]: string }\n): Logger | undefined {\n try {\n const path = new URL(url, \"https://example.com\").pathname;\n const parsed = parseUrlComponents(path);\n if (parsed.type !== \"invoke\") {\n return undefined;\n }\n const invocationId = invocationIdFromHeaders(headers);\n return createLogger(\n loggerTransport,\n LogSource.SYSTEM,\n new LoggerContext(\n invocationId,\n parsed.componentName,\n parsed.handlerName,\n undefined,\n undefined,\n additionalContext\n )\n );\n } catch {\n return undefined;\n }\n}\n\nexport function invocationIdFromHeaders(headers: Headers) {\n const invocationIdHeader = headers[\"x-restate-invocation-id\"];\n const invocationId =\n typeof invocationIdHeader === \"string\"\n ? invocationIdHeader\n : Array.isArray(invocationIdHeader)\n ? (invocationIdHeader[0] ?? \"unknown id\")\n : \"unknown id\";\n return invocationId;\n}\n\nexport function errorResponse(code: number, message: string): RestateResponse {\n return simpleResponse(\n code,\n {\n \"content-type\": \"application/json\",\n \"x-restate-server\": X_RESTATE_SERVER,\n },\n new TextEncoder().encode(JSON.stringify({ message }))\n );\n}\n\nexport function simpleResponse(\n statusCode: number,\n headers: ResponseHeaders,\n body: Uint8Array\n): RestateResponse {\n return {\n
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/endpoint/handlers/utils.ts"],"sourcesContent":["import {\n LoggerContext,\n LogSource,\n LoggerTransport,\n} from \"../../logging/logger_transport.js\";\nimport type {\n Headers,\n InputReader,\n ResponseHeaders,\n RestateResponse,\n} from \"./types.js\";\nimport { createLogger, Logger } from \"../../logging/logger.js\";\nimport { parseUrlComponents } from \"../components.js\";\nimport { X_RESTATE_SERVER } from \"../../user_agent.js\";\n\nexport function tryCreateContextualLogger(\n loggerTransport: LoggerTransport,\n url: string,\n headers: Headers,\n additionalContext?: { [name: string]: string }\n): Logger | undefined {\n try {\n const path = new URL(url, \"https://example.com\").pathname;\n const parsed = parseUrlComponents(path);\n if (parsed.type !== \"invoke\") {\n return undefined;\n }\n const invocationId = invocationIdFromHeaders(headers);\n return createLogger(\n loggerTransport,\n LogSource.SYSTEM,\n new LoggerContext(\n invocationId,\n parsed.componentName,\n parsed.handlerName,\n undefined,\n undefined,\n additionalContext\n )\n );\n } catch {\n return undefined;\n }\n}\n\nexport function invocationIdFromHeaders(headers: Headers) {\n const invocationIdHeader = headers[\"x-restate-invocation-id\"];\n const invocationId =\n typeof invocationIdHeader === \"string\"\n ? invocationIdHeader\n : Array.isArray(invocationIdHeader)\n ? (invocationIdHeader[0] ?? \"unknown id\")\n : \"unknown id\";\n return invocationId;\n}\n\nexport function errorResponse(code: number, message: string): RestateResponse {\n return simpleResponse(\n code,\n {\n \"content-type\": \"application/json\",\n \"x-restate-server\": X_RESTATE_SERVER,\n },\n new TextEncoder().encode(JSON.stringify({ message }))\n );\n}\n\nexport function simpleResponse(\n statusCode: number,\n headers: ResponseHeaders,\n body: Uint8Array\n): RestateResponse {\n return {\n async process({ inputReader, outputWriter, writeHead }): Promise<void> {\n writeHead(statusCode, headers);\n\n // Drain the input stream\n while (true) {\n const { done } = await inputReader.next();\n if (done) break;\n }\n\n await outputWriter.write(body);\n // This closes both the writer and the stream!!!\n await outputWriter.close();\n },\n };\n}\n\nexport function emptyInputReader(): InputReader {\n return (async function* () {})()[Symbol.asyncIterator]();\n}\n\n/**\n * Bundles a `writeHead` callback with a Promise that resolves once the head\n * is committed. Used by adapters (fetch, lambda) that need to observe the\n * head commit from outside the `process()` call.\n */\nexport function captureHead(): {\n writeHead: (statusCode: number, headers: ResponseHeaders) => void;\n head: Promise<{ statusCode: number; headers: ResponseHeaders }>;\n} {\n const { promise, resolve } = Promise.withResolvers<{\n statusCode: number;\n headers: ResponseHeaders;\n }>();\n return {\n writeHead: (statusCode, headers) => {\n resolve({ statusCode, headers: { ...headers } });\n },\n head: promise,\n };\n}\n"],"mappings":";;;;;;AAeA,SAAgB,0BACd,iBACA,KACA,SACA,mBACoB;AACpB,KAAI;EACF,MAAM,OAAO,IAAI,IAAI,KAAK,sBAAsB,CAAC;EACjD,MAAM,SAAS,mBAAmB,KAAK;AACvC,MAAI,OAAO,SAAS,SAClB;EAEF,MAAM,eAAe,wBAAwB,QAAQ;AACrD,SAAO,aACL,iBACA,UAAU,QACV,IAAI,cACF,cACA,OAAO,eACP,OAAO,aACP,QACA,QACA,kBACD,CACF;SACK;AACN;;;AAIJ,SAAgB,wBAAwB,SAAkB;CACxD,MAAM,qBAAqB,QAAQ;AAOnC,QALE,OAAO,uBAAuB,WAC1B,qBACA,MAAM,QAAQ,mBAAmB,GAC9B,mBAAmB,MAAM,eAC1B;;AAIV,SAAgB,cAAc,MAAc,SAAkC;AAC5E,QAAO,eACL,MACA;EACE,gBAAgB;EAChB,oBAAoB;EACrB,EACD,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU,EAAE,SAAS,CAAC,CAAC,CACtD;;AAGH,SAAgB,eACd,YACA,SACA,MACiB;AACjB,QAAO,EACL,MAAM,QAAQ,EAAE,aAAa,cAAc,aAA4B;AACrE,YAAU,YAAY,QAAQ;AAG9B,SAAO,MAAM;GACX,MAAM,EAAE,SAAS,MAAM,YAAY,MAAM;AACzC,OAAI,KAAM;;AAGZ,QAAM,aAAa,MAAM,KAAK;AAE9B,QAAM,aAAa,OAAO;IAE7B;;AAGH,SAAgB,mBAAgC;AAC9C,SAAQ,mBAAmB,KAAK,CAAC,OAAO,gBAAgB;;;;;;;AAQ1D,SAAgB,cAGd;CACA,MAAM,EAAE,SAAS,YAAY,QAAQ,eAGjC;AACJ,QAAO;EACL,YAAY,YAAY,YAAY;AAClC,WAAQ;IAAE;IAAY,SAAS,EAAE,GAAG,SAAS;IAAE,CAAC;;EAElD,MAAM;EACP"}
|
|
@@ -74,19 +74,22 @@ function nodeHandlerImpl(endpoint, protocolMode) {
|
|
|
74
74
|
const handler = require_generic.createRestateHandler(endpoint, protocolMode, {});
|
|
75
75
|
return (httpRequest, httpResponse) => {
|
|
76
76
|
const url = httpRequest.url;
|
|
77
|
+
const inputReader = inputReaderAdapter(httpRequest);
|
|
78
|
+
const outputWriter = outputWriterAdapter(httpResponse);
|
|
79
|
+
const res = httpResponse;
|
|
77
80
|
const abortController = new AbortController();
|
|
78
81
|
httpRequest.on("close", () => {
|
|
79
82
|
abortController.abort();
|
|
80
83
|
});
|
|
81
|
-
const
|
|
84
|
+
const writeHead = res.writeHead.bind(res);
|
|
85
|
+
handler.handle({
|
|
82
86
|
url,
|
|
83
87
|
headers: httpRequest.headers,
|
|
84
88
|
extraArgs: []
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
outputWriter: outputWriterAdapter(httpResponse),
|
|
89
|
+
}).process({
|
|
90
|
+
inputReader,
|
|
91
|
+
outputWriter,
|
|
92
|
+
writeHead,
|
|
90
93
|
abortSignal: abortController.signal
|
|
91
94
|
}).catch((e) => {
|
|
92
95
|
const error = require_errors.ensureError(e);
|
|
@@ -72,19 +72,22 @@ function nodeHandlerImpl(endpoint, protocolMode) {
|
|
|
72
72
|
const handler = createRestateHandler(endpoint, protocolMode, {});
|
|
73
73
|
return (httpRequest, httpResponse) => {
|
|
74
74
|
const url = httpRequest.url;
|
|
75
|
+
const inputReader = inputReaderAdapter(httpRequest);
|
|
76
|
+
const outputWriter = outputWriterAdapter(httpResponse);
|
|
77
|
+
const res = httpResponse;
|
|
75
78
|
const abortController = new AbortController();
|
|
76
79
|
httpRequest.on("close", () => {
|
|
77
80
|
abortController.abort();
|
|
78
81
|
});
|
|
79
|
-
const
|
|
82
|
+
const writeHead = res.writeHead.bind(res);
|
|
83
|
+
handler.handle({
|
|
80
84
|
url,
|
|
81
85
|
headers: httpRequest.headers,
|
|
82
86
|
extraArgs: []
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
outputWriter: outputWriterAdapter(httpResponse),
|
|
87
|
+
}).process({
|
|
88
|
+
inputReader,
|
|
89
|
+
outputWriter,
|
|
90
|
+
writeHead,
|
|
88
91
|
abortSignal: abortController.signal
|
|
89
92
|
}).catch((e) => {
|
|
90
93
|
const error = ensureError(e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node_endpoint.js","names":[],"sources":["../../src/endpoint/node_endpoint.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport type { RestateEndpoint } from \"../index.js\";\nimport type {\n JournalValueCodec,\n ServiceDefinition,\n VirtualObjectDefinition,\n WorkflowDefinition,\n} from \"@restatedev/restate-sdk-core\";\nimport { IncomingMessage, ServerResponse } from \"node:http\";\nimport { Http2ServerRequest, Http2ServerResponse } from \"node:http2\";\nimport * as http2 from \"node:http2\";\nimport type { Endpoint } from \"./endpoint.js\";\nimport { EndpointBuilder } from \"./endpoint.js\";\nimport { createRestateHandler } from \"./handlers/generic.js\";\nimport { ensureError } from \"../types/errors.js\";\nimport type { LoggerTransport } from \"../logging/logger_transport.js\";\nimport type { DefaultServiceOptions } from \"../endpoint.js\";\nimport { tryCreateContextualLogger } from \"./handlers/utils.js\";\nimport type { InputReader, OutputWriter } from \"./handlers/types.js\";\nimport type { ProtocolMode } from \"./discovery.js\";\n\nexport class NodeEndpoint implements RestateEndpoint {\n private builder: EndpointBuilder = new EndpointBuilder();\n\n public bind<P extends string, M>(\n definition:\n | ServiceDefinition<P, M>\n | VirtualObjectDefinition<P, M>\n | WorkflowDefinition<P, M>\n ): RestateEndpoint {\n this.builder.bind(definition);\n return this;\n }\n\n public withIdentityV1(...keys: string[]): RestateEndpoint {\n this.builder.addIdentityKeys(...keys);\n return this;\n }\n\n public defaultServiceOptions(\n options: DefaultServiceOptions\n ): RestateEndpoint {\n this.builder.setDefaultServiceOptions(options);\n return this;\n }\n\n public setLogger(logger: LoggerTransport): RestateEndpoint {\n this.builder.setLogger(logger);\n return this;\n }\n\n public journalValueCodecProvider(\n codecProvider: () => Promise<JournalValueCodec>\n ): RestateEndpoint {\n this.builder.setJournalValueCodecProvider(codecProvider);\n return this;\n }\n\n http2Handler(options?: {\n bidirectional?: boolean;\n }): (request: Http2ServerRequest, response: Http2ServerResponse) => void {\n return nodeHttp2Handler(\n this.builder.build(),\n options?.bidirectional === false ? \"REQUEST_RESPONSE\" : \"BIDI_STREAM\"\n );\n }\n\n http1Handler(options?: {\n bidirectional?: boolean;\n }): (request: IncomingMessage, response: ServerResponse) => void {\n return nodeHttp1Handler(\n this.builder.build(),\n options?.bidirectional ? \"BIDI_STREAM\" : \"REQUEST_RESPONSE\"\n );\n }\n\n handler(options?: { bidirectional?: boolean }): {\n (request: IncomingMessage, response: ServerResponse): void;\n (request: Http2ServerRequest, response: Http2ServerResponse): void;\n } {\n const endpoint = this.builder.build();\n const h2Handler = nodeHttp2Handler(\n endpoint,\n options?.bidirectional === false ? \"REQUEST_RESPONSE\" : \"BIDI_STREAM\"\n );\n const h1Handler = nodeHttp1Handler(\n endpoint,\n options?.bidirectional ? \"BIDI_STREAM\" : \"REQUEST_RESPONSE\"\n );\n\n return ((\n request: IncomingMessage | Http2ServerRequest,\n response: ServerResponse | Http2ServerResponse\n ) => {\n if (request.httpVersionMajor >= 2) {\n h2Handler(\n request as Http2ServerRequest,\n response as Http2ServerResponse\n );\n } else {\n h1Handler(request as IncomingMessage, response as ServerResponse);\n }\n }) as {\n (request: IncomingMessage, response: ServerResponse): void;\n (request: Http2ServerRequest, response: Http2ServerResponse): void;\n };\n }\n\n listen(port?: number): Promise<number> {\n const endpoint = this.builder.build();\n\n const actualPort = port ?? parseInt(process.env.PORT ?? \"9080\");\n endpoint.rlog.info(`Restate SDK started listening on ${actualPort}...`);\n\n const server = http2.createServer(\n nodeHttp2Handler(endpoint, \"BIDI_STREAM\")\n );\n\n return new Promise((resolve, reject) => {\n let failed = false;\n server.once(\"error\", (e: Error) => {\n failed = true;\n reject(e);\n });\n server.listen(actualPort, () => {\n if (failed) {\n return;\n }\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n reject(\n new TypeError(\n \"endpoint.listen() currently supports only binding to a PORT\"\n )\n );\n } else {\n resolve(address.port);\n }\n });\n });\n }\n}\n\nfunction nodeHttp1Handler(\n endpoint: Endpoint,\n protocolMode: ProtocolMode\n): (request: IncomingMessage, response: ServerResponse) => void {\n return nodeHandlerImpl(endpoint, protocolMode);\n}\n\nfunction nodeHttp2Handler(\n endpoint: Endpoint,\n protocolMode: ProtocolMode\n): (request: Http2ServerRequest, response: Http2ServerResponse) => void {\n return nodeHandlerImpl(endpoint, protocolMode);\n}\n\nfunction nodeHandlerImpl(\n endpoint: Endpoint,\n protocolMode: ProtocolMode\n): (\n request: Http2ServerRequest | IncomingMessage,\n response: Http2ServerResponse | ServerResponse\n) => void {\n const handler = createRestateHandler(endpoint, protocolMode, {});\n\n return (httpRequest, httpResponse) => {\n const url = httpRequest.url!;\n\n // Abort controller used to cleanup resources at the end of this stream lifecycle\n const abortController = new AbortController();\n httpRequest.on(\"close\", () => {\n abortController.abort();\n });\n\n const restateResponse = handler.handle({\n url,\n headers: httpRequest.headers,\n extraArgs: [],\n });\n const res = httpResponse as NodeWritableResponse;\n res.writeHead(restateResponse.statusCode, restateResponse.headers);\n\n restateResponse\n .process({\n inputReader: inputReaderAdapter(httpRequest),\n outputWriter: outputWriterAdapter(httpResponse),\n abortSignal: abortController.signal,\n })\n .catch((e) => {\n // handle should never throw\n const error = ensureError(e);\n const logger =\n tryCreateContextualLogger(\n endpoint.loggerTransport,\n url,\n httpRequest.headers\n ) ?? endpoint.rlog;\n logger.error(\"Unexpected error: \" + (error.stack ?? error.message));\n });\n };\n}\n\n// Both ServerResponse and Http2ServerResponse satisfy this interface.\n// We use it to avoid TS union overload incompatibilities.\ninterface NodeWritableResponse {\n writeHead(statusCode: number, headers: Record<string, string>): void;\n write(chunk: Uint8Array, callback: (err?: Error | null) => void): boolean;\n end(callback: () => void): void;\n}\n\nfunction inputReaderAdapter(\n request: Http2ServerRequest | IncomingMessage\n): InputReader {\n return (request as AsyncIterable<Uint8Array>)[Symbol.asyncIterator]();\n}\n\nfunction outputWriterAdapter(\n response: Http2ServerResponse | ServerResponse\n): OutputWriter {\n const res = response as NodeWritableResponse;\n return {\n write: function (value: Uint8Array): Promise<void> {\n return new Promise((resolve, reject) => {\n res.write(value, (err) => (err ? reject(err) : resolve()));\n });\n },\n close: function (): Promise<void> {\n return new Promise((resolve) => {\n res.end(() => resolve());\n });\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"node_endpoint.js","names":[],"sources":["../../src/endpoint/node_endpoint.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport type { RestateEndpoint } from \"../index.js\";\nimport type {\n JournalValueCodec,\n ServiceDefinition,\n VirtualObjectDefinition,\n WorkflowDefinition,\n} from \"@restatedev/restate-sdk-core\";\nimport { IncomingMessage, ServerResponse } from \"node:http\";\nimport { Http2ServerRequest, Http2ServerResponse } from \"node:http2\";\nimport * as http2 from \"node:http2\";\nimport type { Endpoint } from \"./endpoint.js\";\nimport { EndpointBuilder } from \"./endpoint.js\";\nimport { createRestateHandler } from \"./handlers/generic.js\";\nimport { ensureError } from \"../types/errors.js\";\nimport type { LoggerTransport } from \"../logging/logger_transport.js\";\nimport type { DefaultServiceOptions } from \"../endpoint.js\";\nimport { tryCreateContextualLogger } from \"./handlers/utils.js\";\nimport type { InputReader, OutputWriter } from \"./handlers/types.js\";\nimport type { ProtocolMode } from \"./discovery.js\";\n\nexport class NodeEndpoint implements RestateEndpoint {\n private builder: EndpointBuilder = new EndpointBuilder();\n\n public bind<P extends string, M>(\n definition:\n | ServiceDefinition<P, M>\n | VirtualObjectDefinition<P, M>\n | WorkflowDefinition<P, M>\n ): RestateEndpoint {\n this.builder.bind(definition);\n return this;\n }\n\n public withIdentityV1(...keys: string[]): RestateEndpoint {\n this.builder.addIdentityKeys(...keys);\n return this;\n }\n\n public defaultServiceOptions(\n options: DefaultServiceOptions\n ): RestateEndpoint {\n this.builder.setDefaultServiceOptions(options);\n return this;\n }\n\n public setLogger(logger: LoggerTransport): RestateEndpoint {\n this.builder.setLogger(logger);\n return this;\n }\n\n public journalValueCodecProvider(\n codecProvider: () => Promise<JournalValueCodec>\n ): RestateEndpoint {\n this.builder.setJournalValueCodecProvider(codecProvider);\n return this;\n }\n\n http2Handler(options?: {\n bidirectional?: boolean;\n }): (request: Http2ServerRequest, response: Http2ServerResponse) => void {\n return nodeHttp2Handler(\n this.builder.build(),\n options?.bidirectional === false ? \"REQUEST_RESPONSE\" : \"BIDI_STREAM\"\n );\n }\n\n http1Handler(options?: {\n bidirectional?: boolean;\n }): (request: IncomingMessage, response: ServerResponse) => void {\n return nodeHttp1Handler(\n this.builder.build(),\n options?.bidirectional ? \"BIDI_STREAM\" : \"REQUEST_RESPONSE\"\n );\n }\n\n handler(options?: { bidirectional?: boolean }): {\n (request: IncomingMessage, response: ServerResponse): void;\n (request: Http2ServerRequest, response: Http2ServerResponse): void;\n } {\n const endpoint = this.builder.build();\n const h2Handler = nodeHttp2Handler(\n endpoint,\n options?.bidirectional === false ? \"REQUEST_RESPONSE\" : \"BIDI_STREAM\"\n );\n const h1Handler = nodeHttp1Handler(\n endpoint,\n options?.bidirectional ? \"BIDI_STREAM\" : \"REQUEST_RESPONSE\"\n );\n\n return ((\n request: IncomingMessage | Http2ServerRequest,\n response: ServerResponse | Http2ServerResponse\n ) => {\n if (request.httpVersionMajor >= 2) {\n h2Handler(\n request as Http2ServerRequest,\n response as Http2ServerResponse\n );\n } else {\n h1Handler(request as IncomingMessage, response as ServerResponse);\n }\n }) as {\n (request: IncomingMessage, response: ServerResponse): void;\n (request: Http2ServerRequest, response: Http2ServerResponse): void;\n };\n }\n\n listen(port?: number): Promise<number> {\n const endpoint = this.builder.build();\n\n const actualPort = port ?? parseInt(process.env.PORT ?? \"9080\");\n endpoint.rlog.info(`Restate SDK started listening on ${actualPort}...`);\n\n const server = http2.createServer(\n nodeHttp2Handler(endpoint, \"BIDI_STREAM\")\n );\n\n return new Promise((resolve, reject) => {\n let failed = false;\n server.once(\"error\", (e: Error) => {\n failed = true;\n reject(e);\n });\n server.listen(actualPort, () => {\n if (failed) {\n return;\n }\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n reject(\n new TypeError(\n \"endpoint.listen() currently supports only binding to a PORT\"\n )\n );\n } else {\n resolve(address.port);\n }\n });\n });\n }\n}\n\nfunction nodeHttp1Handler(\n endpoint: Endpoint,\n protocolMode: ProtocolMode\n): (request: IncomingMessage, response: ServerResponse) => void {\n return nodeHandlerImpl(endpoint, protocolMode);\n}\n\nfunction nodeHttp2Handler(\n endpoint: Endpoint,\n protocolMode: ProtocolMode\n): (request: Http2ServerRequest, response: Http2ServerResponse) => void {\n return nodeHandlerImpl(endpoint, protocolMode);\n}\n\nfunction nodeHandlerImpl(\n endpoint: Endpoint,\n protocolMode: ProtocolMode\n): (\n request: Http2ServerRequest | IncomingMessage,\n response: Http2ServerResponse | ServerResponse\n) => void {\n const handler = createRestateHandler(endpoint, protocolMode, {});\n\n return (httpRequest, httpResponse) => {\n const url = httpRequest.url!;\n const inputReader = inputReaderAdapter(httpRequest);\n const outputWriter = outputWriterAdapter(httpResponse);\n const res = httpResponse as NodeWritableResponse;\n\n // Abort controller used to cleanup resources at the end of this stream lifecycle\n const abortController = new AbortController();\n httpRequest.on(\"close\", () => {\n abortController.abort();\n });\n\n const writeHead = res.writeHead.bind(res);\n\n // handle should never throw\n const restateResponse = handler.handle({\n url,\n headers: httpRequest.headers,\n extraArgs: [],\n });\n\n restateResponse\n .process({\n inputReader,\n outputWriter,\n writeHead,\n abortSignal: abortController.signal,\n })\n .catch((e) => {\n // Responses handle their own errors before rejecting; anything\n // reaching here is an unexpected failure — just log.\n const error = ensureError(e);\n const logger =\n tryCreateContextualLogger(\n endpoint.loggerTransport,\n url,\n httpRequest.headers\n ) ?? endpoint.rlog;\n logger.error(\"Unexpected error: \" + (error.stack ?? error.message));\n });\n };\n}\n\n// Both ServerResponse and Http2ServerResponse satisfy this interface.\n// We use it to avoid TS union overload incompatibilities.\ninterface NodeWritableResponse {\n writeHead(statusCode: number, headers: Record<string, string>): void;\n write(chunk: Uint8Array, callback: (err?: Error | null) => void): boolean;\n end(callback: () => void): void;\n}\n\nfunction inputReaderAdapter(\n request: Http2ServerRequest | IncomingMessage\n): InputReader {\n return (request as AsyncIterable<Uint8Array>)[Symbol.asyncIterator]();\n}\n\nfunction outputWriterAdapter(\n response: Http2ServerResponse | ServerResponse\n): OutputWriter {\n const res = response as NodeWritableResponse;\n return {\n write: function (value: Uint8Array): Promise<void> {\n return new Promise((resolve, reject) => {\n res.write(value, (err) => (err ? reject(err) : resolve()));\n });\n },\n close: function (): Promise<void> {\n return new Promise((resolve) => {\n res.end(() => resolve());\n });\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/io.cjs
CHANGED
|
@@ -6,10 +6,12 @@ const require_promises = require('./promises.cjs');
|
|
|
6
6
|
*/
|
|
7
7
|
var InputPump = class {
|
|
8
8
|
currentRead;
|
|
9
|
+
closed;
|
|
9
10
|
constructor(coreVm, inputReader, errorCallback) {
|
|
10
11
|
this.coreVm = coreVm;
|
|
11
12
|
this.inputReader = inputReader;
|
|
12
13
|
this.errorCallback = errorCallback;
|
|
14
|
+
this.closed = false;
|
|
13
15
|
}
|
|
14
16
|
awaitNextProgress() {
|
|
15
17
|
if (this.currentRead === void 0) this.currentRead = this.readNext().finally(() => {
|
|
@@ -18,6 +20,7 @@ var InputPump = class {
|
|
|
18
20
|
return new Promise((resolve) => this.currentRead?.finally(resolve));
|
|
19
21
|
}
|
|
20
22
|
async readNext() {
|
|
23
|
+
if (this.closed) return require_promises.pendingPromise();
|
|
21
24
|
let nextValue;
|
|
22
25
|
try {
|
|
23
26
|
nextValue = await this.inputReader.next();
|
|
@@ -25,8 +28,10 @@ var InputPump = class {
|
|
|
25
28
|
this.errorCallback(e);
|
|
26
29
|
return require_promises.pendingPromise();
|
|
27
30
|
}
|
|
28
|
-
if (nextValue.done)
|
|
29
|
-
|
|
31
|
+
if (nextValue.done) {
|
|
32
|
+
this.closed = true;
|
|
33
|
+
this.coreVm.notify_input_closed();
|
|
34
|
+
} else if (nextValue.value !== void 0) this.coreVm.notify_input(nextValue.value);
|
|
30
35
|
}
|
|
31
36
|
};
|
|
32
37
|
/**
|
package/dist/io.js
CHANGED
|
@@ -6,10 +6,12 @@ import { pendingPromise } from "./promises.js";
|
|
|
6
6
|
*/
|
|
7
7
|
var InputPump = class {
|
|
8
8
|
currentRead;
|
|
9
|
+
closed;
|
|
9
10
|
constructor(coreVm, inputReader, errorCallback) {
|
|
10
11
|
this.coreVm = coreVm;
|
|
11
12
|
this.inputReader = inputReader;
|
|
12
13
|
this.errorCallback = errorCallback;
|
|
14
|
+
this.closed = false;
|
|
13
15
|
}
|
|
14
16
|
awaitNextProgress() {
|
|
15
17
|
if (this.currentRead === void 0) this.currentRead = this.readNext().finally(() => {
|
|
@@ -18,6 +20,7 @@ var InputPump = class {
|
|
|
18
20
|
return new Promise((resolve) => this.currentRead?.finally(resolve));
|
|
19
21
|
}
|
|
20
22
|
async readNext() {
|
|
23
|
+
if (this.closed) return pendingPromise();
|
|
21
24
|
let nextValue;
|
|
22
25
|
try {
|
|
23
26
|
nextValue = await this.inputReader.next();
|
|
@@ -25,8 +28,10 @@ var InputPump = class {
|
|
|
25
28
|
this.errorCallback(e);
|
|
26
29
|
return pendingPromise();
|
|
27
30
|
}
|
|
28
|
-
if (nextValue.done)
|
|
29
|
-
|
|
31
|
+
if (nextValue.done) {
|
|
32
|
+
this.closed = true;
|
|
33
|
+
this.coreVm.notify_input_closed();
|
|
34
|
+
} else if (nextValue.value !== void 0) this.coreVm.notify_input(nextValue.value);
|
|
30
35
|
}
|
|
31
36
|
};
|
|
32
37
|
/**
|
package/dist/io.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"io.js","names":["coreVm: vm.WasmVM","inputReader: InputReader","errorCallback: (e: any) => void","outputWriter: OutputWriter"],"sources":["../src/io.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2025 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type * as vm from \"./endpoint/handlers/vm/sdk_shared_core_wasm_bindings.js\";\nimport { pendingPromise } from \"./promises.js\";\nimport { InputReader, OutputWriter } from \"./endpoint/handlers/types.js\";\n\n/**\n * Adapter between input stream and vm. It moves forward when [awaitNextProgress] is invoked.\n */\nexport class InputPump {\n private currentRead?: Promise<void>;\n\n constructor(\n private readonly coreVm: vm.WasmVM,\n private readonly inputReader: InputReader,\n private readonly errorCallback: (e: any) => void\n ) {}\n\n // This function triggers a read on the input reader,\n // and will notify the caller that a read was executed\n // and the result was piped in the state machine.\n awaitNextProgress(): Promise<void> {\n if (this.currentRead === undefined) {\n // Register a new read\n this.currentRead = this.readNext().finally(() => {\n this.currentRead = undefined;\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return new Promise<void>((resolve) => this.currentRead?.finally(resolve));\n }\n\n private async readNext(): Promise<void> {\n // Take input, and notify it to the vm\n let nextValue;\n try {\n nextValue = await this.inputReader.next();\n } catch (e) {\n this.errorCallback(e);\n return pendingPromise<void>();\n }\n if (nextValue.done) {\n this.coreVm.notify_input_closed();\n } else if (nextValue.value !== undefined) {\n this.coreVm.notify_input(nextValue.value);\n }\n }\n}\n\n/**\n * Adapter between output stream and vm. It moves forward when [awaitNextProgress] is invoked.\n */\nexport class OutputPump {\n constructor(\n private readonly coreVm: vm.WasmVM,\n private readonly outputWriter: OutputWriter\n ) {}\n\n async awaitNextProgress() {\n const nextOutput = this.coreVm.take_output() as\n | Uint8Array\n | null\n | undefined;\n if (nextOutput instanceof Uint8Array) {\n await this.outputWriter.write(nextOutput);\n }\n }\n}\n"],"mappings":";;;;;;AAoBA,IAAa,YAAb,MAAuB;CACrB,AAAQ;CAER,YACE,AAAiBA,QACjB,AAAiBC,aACjB,AAAiBC,eACjB;EAHiB;EACA;EACA;;
|
|
1
|
+
{"version":3,"file":"io.js","names":["coreVm: vm.WasmVM","inputReader: InputReader","errorCallback: (e: any) => void","outputWriter: OutputWriter"],"sources":["../src/io.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2025 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type * as vm from \"./endpoint/handlers/vm/sdk_shared_core_wasm_bindings.js\";\nimport { pendingPromise } from \"./promises.js\";\nimport { InputReader, OutputWriter } from \"./endpoint/handlers/types.js\";\n\n/**\n * Adapter between input stream and vm. It moves forward when [awaitNextProgress] is invoked.\n */\nexport class InputPump {\n private currentRead?: Promise<void>;\n private closed: boolean;\n\n constructor(\n private readonly coreVm: vm.WasmVM,\n private readonly inputReader: InputReader,\n private readonly errorCallback: (e: any) => void\n ) {\n this.closed = false;\n }\n\n // This function triggers a read on the input reader,\n // and will notify the caller that a read was executed\n // and the result was piped in the state machine.\n awaitNextProgress(): Promise<void> {\n if (this.currentRead === undefined) {\n // Register a new read\n this.currentRead = this.readNext().finally(() => {\n this.currentRead = undefined;\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return new Promise<void>((resolve) => this.currentRead?.finally(resolve));\n }\n\n private async readNext(): Promise<void> {\n if (this.closed) {\n return pendingPromise<void>();\n }\n // Take input, and notify it to the vm\n let nextValue;\n try {\n nextValue = await this.inputReader.next();\n } catch (e) {\n this.errorCallback(e);\n return pendingPromise<void>();\n }\n if (nextValue.done) {\n this.closed = true;\n this.coreVm.notify_input_closed();\n } else if (nextValue.value !== undefined) {\n this.coreVm.notify_input(nextValue.value);\n }\n }\n}\n\n/**\n * Adapter between output stream and vm. It moves forward when [awaitNextProgress] is invoked.\n */\nexport class OutputPump {\n constructor(\n private readonly coreVm: vm.WasmVM,\n private readonly outputWriter: OutputWriter\n ) {}\n\n async awaitNextProgress() {\n const nextOutput = this.coreVm.take_output() as\n | Uint8Array\n | null\n | undefined;\n if (nextOutput instanceof Uint8Array) {\n await this.outputWriter.write(nextOutput);\n }\n }\n}\n"],"mappings":";;;;;;AAoBA,IAAa,YAAb,MAAuB;CACrB,AAAQ;CACR,AAAQ;CAER,YACE,AAAiBA,QACjB,AAAiBC,aACjB,AAAiBC,eACjB;EAHiB;EACA;EACA;AAEjB,OAAK,SAAS;;CAMhB,oBAAmC;AACjC,MAAI,KAAK,gBAAgB,OAEvB,MAAK,cAAc,KAAK,UAAU,CAAC,cAAc;AAC/C,QAAK,cAAc;IACnB;AAIJ,SAAO,IAAI,SAAe,YAAY,KAAK,aAAa,QAAQ,QAAQ,CAAC;;CAG3E,MAAc,WAA0B;AACtC,MAAI,KAAK,OACP,QAAO,gBAAsB;EAG/B,IAAI;AACJ,MAAI;AACF,eAAY,MAAM,KAAK,YAAY,MAAM;WAClC,GAAG;AACV,QAAK,cAAc,EAAE;AACrB,UAAO,gBAAsB;;AAE/B,MAAI,UAAU,MAAM;AAClB,QAAK,SAAS;AACd,QAAK,OAAO,qBAAqB;aACxB,UAAU,UAAU,OAC7B,MAAK,OAAO,aAAa,UAAU,MAAM;;;;;;AAQ/C,IAAa,aAAb,MAAwB;CACtB,YACE,AAAiBF,QACjB,AAAiBG,cACjB;EAFiB;EACA;;CAGnB,MAAM,oBAAoB;EACxB,MAAM,aAAa,KAAK,OAAO,aAAa;AAI5C,MAAI,sBAAsB,WACxB,OAAM,KAAK,aAAa,MAAM,WAAW"}
|
package/dist/package.cjs
CHANGED
package/dist/package.js
CHANGED
package/dist/package.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@restatedev/restate-sdk\",\n \"version\": \"1.
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@restatedev/restate-sdk\",\n \"version\": \"1.14.0\",\n \"description\": \"Typescript SDK for Restate\",\n \"author\": \"Restate Developers\",\n \"email\": \"code@restate.dev\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/restatedev/sdk-typescript#readme\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/restatedev/sdk-typescript.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/restatedev/sdk-typescript/issues\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.cts\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./fetch\": {\n \"import\": \"./dist/fetch.js\",\n \"require\": \"./dist/fetch.cjs\"\n },\n \"./lambda\": {\n \"import\": \"./dist/lambda.js\",\n \"require\": \"./dist/lambda.cjs\"\n },\n \"./node\": {\n \"import\": \"./dist/node.js\",\n \"require\": \"./dist/node.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"test\": \"turbo run _test --filter={.}...\",\n \"_test\": \"vitest run\",\n \"build\": \"turbo run _build --filter={.}...\",\n \"_build\": \"tsc --noEmit && tsdown\",\n \"dev\": \"tsc --noEmit --watch\",\n \"clean\": \"rm -rf dist *.tsbuildinfo .turbo\",\n \"check:types\": \"turbo run _check:types --filter={.}...\",\n \"_check:types\": \"tsc --noEmit --project tsconfig.build.json\",\n \"lint\": \"eslint .\",\n \"check:exports\": \"turbo run _check:exports --filter={.}...\",\n \"_check:exports\": \"attw --pack .\",\n \"check:api\": \"turbo run _check:api --filter={.}...\",\n \"_check:api\": \"api-extractor run --local && api-extractor run --local --config api-extractor.fetch.json && api-extractor run --local --config api-extractor.lambda.json && api-extractor run --local --config api-extractor.node.json\",\n \"prepublishOnly\": \"pnpm -w verify\"\n },\n \"dependencies\": {\n \"@restatedev/restate-sdk-core\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"@types/aws-lambda\": \"^8.10.115\"\n },\n \"typesVersions\": {\n \"*\": {\n \"fetch\": [\n \"./dist/fetch.d.ts\"\n ],\n \"lambda\": [\n \"./dist/lambda.d.ts\"\n ],\n \"node\": [\n \"./dist/node.d.ts\"\n ]\n }\n }\n}\n"],"mappings":";cAEa"}
|
package/dist/promises.cjs
CHANGED
|
@@ -253,9 +253,10 @@ var PromisesExecutor = class {
|
|
|
253
253
|
const handles = restatePromise.uncompletedLeaves();
|
|
254
254
|
if (handles.length === 0) return;
|
|
255
255
|
const doProgressResult = this.coreVm.do_progress(new Uint32Array(handles));
|
|
256
|
-
if (doProgressResult === "AnyCompleted") {} else if (doProgressResult === "ReadFromInput"
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
if (doProgressResult === "AnyCompleted") {} else if (doProgressResult === "ReadFromInput" || doProgressResult === "WaitingPendingRun") {
|
|
257
|
+
await this.outputPump.awaitNextProgress();
|
|
258
|
+
await Promise.race([this.inputPump.awaitNextProgress(), this.runClosuresTracker.awaitNextCompletedRun()]);
|
|
259
|
+
} else if (doProgressResult === "CancelSignalReceived") {
|
|
259
260
|
restatePromise.tryCancel();
|
|
260
261
|
return;
|
|
261
262
|
} else {
|
package/dist/promises.js
CHANGED
|
@@ -251,9 +251,10 @@ var PromisesExecutor = class {
|
|
|
251
251
|
const handles = restatePromise.uncompletedLeaves();
|
|
252
252
|
if (handles.length === 0) return;
|
|
253
253
|
const doProgressResult = this.coreVm.do_progress(new Uint32Array(handles));
|
|
254
|
-
if (doProgressResult === "AnyCompleted") {} else if (doProgressResult === "ReadFromInput"
|
|
255
|
-
|
|
256
|
-
|
|
254
|
+
if (doProgressResult === "AnyCompleted") {} else if (doProgressResult === "ReadFromInput" || doProgressResult === "WaitingPendingRun") {
|
|
255
|
+
await this.outputPump.awaitNextProgress();
|
|
256
|
+
await Promise.race([this.inputPump.awaitNextProgress(), this.runClosuresTracker.awaitNextCompletedRun()]);
|
|
257
|
+
} else if (doProgressResult === "CancelSignalReceived") {
|
|
257
258
|
restatePromise.tryCancel();
|
|
258
259
|
return;
|
|
259
260
|
} else {
|
package/dist/promises.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promises.js","names":["handle: number","completer: (\n value: AsyncResultValue,\n prom: CompletablePromise<T>\n ) => Promise<void>","invocationIdPromise: Promise<InvocationId>","childs: Array<InternalRestatePromise<any>>","castedPromises: InternalRestatePromise<any>[]","foundContext: ContextImpl | undefined","inner: InternalRestatePromise<T>","promiseFactory: () => Promise<T>","settled: boolean","coreVm: vm.WasmVM","inputPump: InputPump","outputPump: OutputPump","runClosuresTracker: RunClosuresTracker","errorCallback: (e: any) => void"],"sources":["../src/promises.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2025 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type {\n RestatePromise,\n InvocationId,\n InvocationPromise,\n} from \"./context.js\";\nimport type * as vm from \"./endpoint/handlers/vm/sdk_shared_core_wasm_bindings.js\";\nimport {\n CancelledError,\n RestateError,\n TerminalError,\n TimeoutError,\n} from \"./types/errors.js\";\nimport { CompletablePromise } from \"./utils/completable_promise.js\";\nimport type { ContextImpl, RunClosuresTracker } from \"./context_impl.js\";\nimport { setImmediate } from \"node:timers/promises\";\nimport type { InputPump, OutputPump } from \"./io.js\";\nimport type { Duration } from \"@restatedev/restate-sdk-core\";\n\n// A promise that is never completed\nexport function pendingPromise<T>(): Promise<T> {\n return new Promise<T>(() => {});\n}\n\n// ------ Restate promises ------\n// These promises are \"proxy promises\" that will be handed over to the user,\n// and moved forward by the PromiseExecutor below when the user awaits on them.\n\n/**\n * Returns `true` if the given value is a {@link RestatePromise}.\n *\n * Use this for runtime type detection when you need to distinguish Restate promises\n * from regular promises, e.g. for overload resolution.\n */\nexport function isRestatePromise<T>(p: Promise<T>): p is RestatePromise<T> {\n return p instanceof InternalRestatePromise;\n}\n\nenum PromiseState {\n COMPLETED,\n NOT_COMPLETED,\n}\n\nexport abstract class InternalRestatePromise<T> implements RestatePromise<T> {\n abstract then<TResult1, TResult2>(\n onfulfilled:\n | ((value: T) => PromiseLike<TResult1> | TResult1)\n | undefined\n | null,\n onrejected:\n | ((reason: any) => PromiseLike<TResult2> | TResult2)\n | undefined\n | null\n ): Promise<TResult1 | TResult2>;\n abstract catch<TResult>(\n onrejected:\n | ((reason: any) => PromiseLike<TResult> | TResult)\n | undefined\n | null\n ): Promise<T | TResult>;\n abstract finally(onfinally: (() => void) | undefined | null): Promise<T>;\n\n abstract map<U>(\n mapper: (value?: T, failure?: TerminalError) => U\n ): RestatePromise<U>;\n abstract orTimeout(millis: Duration | number): RestatePromise<T>;\n\n abstract tryCancel(): void;\n abstract tryComplete(): Promise<void>;\n abstract uncompletedLeaves(): Array<number>;\n abstract publicPromise(): Promise<T>;\n\n abstract readonly [Symbol.toStringTag]: string;\n}\n\nexport type AsyncResultValue =\n | \"Empty\"\n | { Success: Uint8Array }\n | { Failure: vm.WasmFailure }\n | { StateKeys: string[] }\n | { InvocationId: string };\n\nconst RESTATE_CTX_SYMBOL = Symbol(\"restateContext\");\n\nfunction extractContext(n: any): ContextImpl | undefined {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return n[RESTATE_CTX_SYMBOL] as ContextImpl | undefined;\n}\n\nabstract class BaseRestatePromise<T> extends InternalRestatePromise<T> {\n [RESTATE_CTX_SYMBOL]: ContextImpl;\n private pollingPromise?: Promise<any>;\n private cancelPromise: CompletablePromise<any> = new CompletablePromise();\n\n protected constructor(ctx: ContextImpl) {\n super();\n this[RESTATE_CTX_SYMBOL] = ctx;\n }\n\n // --- Promise methods\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n this.pollingPromise =\n this.pollingPromise ||\n this[RESTATE_CTX_SYMBOL].promisesExecutor\n .doProgress(this)\n .catch(() => {});\n return this.publicPromiseOrCancelPromise().then(onfulfilled, onrejected);\n }\n\n catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null\n ): Promise<T | TResult> {\n this.pollingPromise =\n this.pollingPromise ||\n this[RESTATE_CTX_SYMBOL].promisesExecutor\n .doProgress(this)\n .catch(() => {});\n return this.publicPromiseOrCancelPromise().catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n this.pollingPromise =\n this.pollingPromise ||\n this[RESTATE_CTX_SYMBOL].promisesExecutor\n .doProgress(this)\n .catch(() => {});\n return this.publicPromiseOrCancelPromise().finally(onfinally);\n }\n\n private publicPromiseOrCancelPromise(): Promise<T> {\n return Promise.race([\n this.cancelPromise.promise as Promise<T>,\n this.publicPromise(),\n ]);\n }\n\n // --- RestatePromise methods\n\n orTimeout(duration: number | Duration): RestatePromise<T> {\n return new CombinatorRestatePromise(\n this[RESTATE_CTX_SYMBOL],\n ([thisPromise, sleepPromise]) => {\n return new Promise((resolve, reject) => {\n thisPromise!.then(resolve, reject);\n sleepPromise!.then(() => {\n reject(new TimeoutError());\n }, reject);\n });\n },\n [\n this,\n this[RESTATE_CTX_SYMBOL].sleep(duration) as InternalRestatePromise<any>,\n ]\n ) as RestatePromise<T>;\n }\n\n map<U>(mapper: (value?: T, failure?: TerminalError) => U): RestatePromise<U> {\n return new MappedRestatePromise(this[RESTATE_CTX_SYMBOL], this, mapper);\n }\n\n tryCancel() {\n this.cancelPromise.reject(new CancelledError());\n }\n\n abstract override tryComplete(): Promise<void>;\n\n abstract override uncompletedLeaves(): Array<number>;\n\n abstract override publicPromise(): Promise<T>;\n\n abstract override [Symbol.toStringTag]: string;\n}\n\nexport class SingleRestatePromise<T> extends BaseRestatePromise<T> {\n private state: PromiseState = PromiseState.NOT_COMPLETED;\n private completablePromise: CompletablePromise<T> = new CompletablePromise();\n\n constructor(\n ctx: ContextImpl,\n readonly handle: number,\n private readonly completer: (\n value: AsyncResultValue,\n prom: CompletablePromise<T>\n ) => Promise<void>\n ) {\n super(ctx);\n }\n\n uncompletedLeaves(): number[] {\n return this.state === PromiseState.COMPLETED ? [] : [this.handle];\n }\n\n async tryComplete(): Promise<void> {\n if (this.state === PromiseState.COMPLETED) {\n return;\n }\n const notification = this[RESTATE_CTX_SYMBOL].coreVm.take_notification(\n this.handle\n );\n if (notification === \"NotReady\") {\n return;\n }\n this.state = PromiseState.COMPLETED;\n await this.completer(notification, this.completablePromise);\n }\n\n publicPromise(): Promise<T> {\n return this.completablePromise.promise;\n }\n\n isCompleted(): boolean {\n return this.state === PromiseState.COMPLETED;\n }\n\n readonly [Symbol.toStringTag] = \"RestateSinglePromise\";\n}\n\nexport class InvocationRestatePromise<T>\n extends SingleRestatePromise<T>\n implements InvocationPromise<T>\n{\n constructor(\n ctx: ContextImpl,\n handle: number,\n completer: (\n value: AsyncResultValue,\n prom: CompletablePromise<T>\n ) => Promise<void>,\n private readonly invocationIdPromise: Promise<InvocationId>\n ) {\n super(ctx, handle, completer);\n }\n\n get invocationId(): Promise<InvocationId> {\n return this.invocationIdPromise;\n }\n}\n\nexport class CombinatorRestatePromise extends BaseRestatePromise<any> {\n private state: PromiseState = PromiseState.NOT_COMPLETED;\n private readonly combinatorPromise: Promise<any>;\n\n constructor(\n ctx: ContextImpl,\n combinatorConstructor: (promises: Promise<any>[]) => Promise<any>,\n readonly childs: Array<InternalRestatePromise<any>>\n ) {\n super(ctx);\n this.combinatorPromise = combinatorConstructor(\n childs.map((p) => p.publicPromise())\n ).finally(() => {\n this.state = PromiseState.COMPLETED;\n });\n }\n\n // Used by static methods of RestatePromise\n public static fromPromises<T extends readonly RestatePromise<unknown>[]>(\n combinatorConstructor: (promises: Promise<any>[]) => Promise<any>,\n promises: T\n ): RestatePromise<unknown> {\n const castedPromises: InternalRestatePromise<any>[] = [];\n let foundContext: ContextImpl | undefined = undefined;\n\n for (const [idx, promise] of promises.entries()) {\n if (!isRestatePromise(promise)) {\n throw new Error(\n `Promise index ${idx} used inside the combinator is not an instance of RestatePromise. This is not supported.`\n );\n } else if (foundContext === undefined) {\n foundContext = extractContext(promise);\n } else {\n const thisContext = extractContext(promise);\n if (thisContext !== undefined && thisContext !== foundContext) {\n throw new Error(\n \"You're mixing up RestatePromises from different RestateContext. This is not supported.\"\n );\n }\n }\n castedPromises.push(promise as InternalRestatePromise<any>);\n }\n\n if (foundContext === undefined) {\n // The only situation where this can happen is when the combined promise contains only ConstRestatePromise as children.\n // In this case, just return back a nice and clean ConstRestatePromise.\n // There is a specific workaround for the funky interface of Promise.race, inside the RestatePromise.race factory method.\n return ConstRestatePromise.fromPromise(\n combinatorConstructor(castedPromises),\n true\n );\n }\n\n return new CombinatorRestatePromise(\n foundContext,\n combinatorConstructor,\n castedPromises\n );\n }\n\n uncompletedLeaves(): number[] {\n return this.state === PromiseState.COMPLETED\n ? []\n : this.childs.flatMap((p) => p.uncompletedLeaves());\n }\n\n async tryComplete(): Promise<void> {\n await Promise.allSettled(this.childs.map((c) => c.tryComplete()));\n }\n\n publicPromise(): Promise<unknown> {\n return this.combinatorPromise;\n }\n\n readonly [Symbol.toStringTag] = \"RestateCombinatorPromise\";\n}\n\nexport class MappedRestatePromise<T, U> extends BaseRestatePromise<U> {\n private publicPromiseMapper: (\n value?: T,\n failure?: TerminalError\n ) => Promise<U>;\n // Memoized so the mapper fires at most once regardless of how many times\n // the promise is awaited / consumed via then/catch/finally/publicPromise.\n private _mappedPromise?: Promise<U>;\n\n constructor(\n ctx: ContextImpl,\n readonly inner: InternalRestatePromise<T>,\n mapper: (value?: T, failure?: TerminalError) => U\n ) {\n super(ctx);\n this.publicPromiseMapper = (value?: T, failure?: TerminalError) => {\n try {\n return Promise.resolve(mapper(value, failure));\n } catch (e) {\n if (e instanceof TerminalError) {\n return Promise.reject(e);\n } else {\n ctx.abortAttempt(e);\n return pendingPromise();\n }\n }\n };\n }\n\n async tryComplete(): Promise<void> {\n await this.inner.tryComplete();\n }\n\n uncompletedLeaves(): number[] {\n return this.inner.uncompletedLeaves();\n }\n\n publicPromise(): Promise<U> {\n return (this._mappedPromise ??= this.buildMappedPromise());\n }\n\n private buildMappedPromise(): Promise<U> {\n const promiseMapper = this.publicPromiseMapper;\n return this.inner.publicPromise().then(\n (t) => promiseMapper(t, undefined),\n (error) => {\n if (error instanceof RestateError) {\n return promiseMapper(undefined, error);\n } else {\n // Something else, just re-throw it\n throw error;\n }\n }\n );\n }\n\n readonly [Symbol.toStringTag] = \"RestateMappedPromise\";\n}\n\nexport class ConstRestatePromise<T> extends InternalRestatePromise<T> {\n private _constPromise?: Promise<T>;\n\n private constructor(\n // Factory for the underlying promise. Called at most once, memoized in\n // `_constPromise`.\n //\n // This way `map` is lazy, making it deterministically invoked on await points.\n private readonly promiseFactory: () => Promise<T>,\n private readonly settled: boolean\n ) {\n super();\n }\n\n private get constPromise(): Promise<T> {\n return (this._constPromise ??= this.promiseFactory());\n }\n\n static resolve<T>(value: T): ConstRestatePromise<Awaited<T>> {\n return new ConstRestatePromise(() => Promise.resolve(value), true);\n }\n\n static reject<T = never>(reason: TerminalError): ConstRestatePromise<T> {\n return new ConstRestatePromise<T>(() => Promise.reject(reason), true);\n }\n\n static pending<T>(): ConstRestatePromise<T> {\n return new ConstRestatePromise<T>(() => pendingPromise<T>(), false);\n }\n\n static fromPromise<T>(\n promise: Promise<T>,\n settled: boolean\n ): ConstRestatePromise<T> {\n return new ConstRestatePromise(() => promise, settled);\n }\n\n // --- Promise methods\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n return this.constPromise.then(onfulfilled, onrejected);\n }\n\n catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null\n ): Promise<T | TResult> {\n return this.constPromise.catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n return this.constPromise.finally(onfinally);\n }\n\n // --- RestatePromise methods\n\n orTimeout(): RestatePromise<T> {\n if (this.settled) return this;\n return ConstRestatePromise.reject(new TimeoutError());\n }\n\n map<U>(mapper: (value?: T, failure?: TerminalError) => U): RestatePromise<U> {\n if (!this.settled) return this as unknown as RestatePromise<U>;\n const selfConstPromise = this.constPromise;\n return new ConstRestatePromise<U>(\n () =>\n selfConstPromise.then(\n (value) => mapper(value, undefined),\n (reason) => mapper(undefined, reason as TerminalError)\n ),\n this.settled\n );\n }\n\n tryCancel() {}\n\n publicPromise(): Promise<T> {\n return this.constPromise;\n }\n\n tryComplete(): Promise<void> {\n return Promise.resolve();\n }\n\n uncompletedLeaves(): Array<number> {\n return [];\n }\n\n readonly [Symbol.toStringTag] = \"ConstRestatePromise\";\n}\n\n/**\n * Promises executor, gluing VM with I/O and Promises given to user space.\n */\nexport class PromisesExecutor {\n constructor(\n private readonly coreVm: vm.WasmVM,\n private readonly inputPump: InputPump,\n private readonly outputPump: OutputPump,\n private readonly runClosuresTracker: RunClosuresTracker,\n private readonly errorCallback: (e: any) => void\n ) {}\n\n async doProgress(restatePromise: InternalRestatePromise<unknown>) {\n // Only the first time try process output\n await this.outputPump.awaitNextProgress();\n await this.doProgressInner(restatePromise);\n }\n\n private async doProgressInner(\n restatePromise: InternalRestatePromise<unknown>\n ) {\n // Try complete the promise\n try {\n await restatePromise.tryComplete();\n } catch (e) {\n // This can happen if either take_notification throws an exception or completer throws an exception.\n // This could either happen for a deserialization issue, or for an SDK bug, but we cover them here.\n this.errorCallback(e);\n return Promise.resolve();\n }\n\n // tl;dr don't touch this, or you can break combineable promises,\n // slinkydeveloper won't be happy about it\n //\n // The reason for this setTimeout is that we need to enqueue the polling after\n // we eventually resolve some promises. This is especially crucial for RestateCombinatorPromise\n // as it flips the completed state using .finally() on the combinator.\n return setImmediate().then(async () => {\n try {\n // Invoke do progress on the vm\n const handles = restatePromise.uncompletedLeaves();\n if (handles.length === 0) {\n // Completed, we're good!\n return;\n }\n const doProgressResult = this.coreVm.do_progress(\n new Uint32Array(handles)\n );\n\n if (doProgressResult === \"AnyCompleted\") {\n // Next recursion will cause the promise to do some progress\n } else if (doProgressResult === \"ReadFromInput\") {\n // Read from input\n await this.inputPump.awaitNextProgress();\n } else if (doProgressResult === \"WaitingPendingRun\") {\n // Wait for any of the pending run to complete\n await this.runClosuresTracker.awaitNextCompletedRun();\n } else if (doProgressResult === \"CancelSignalReceived\") {\n restatePromise.tryCancel();\n return;\n } else {\n // We need to execute a run closure\n this.runClosuresTracker.executeRun(doProgressResult.ExecuteRun);\n // Let the run context switch, then come back to this flow.\n await setImmediate();\n }\n\n // Recursion\n await this.doProgressInner(restatePromise);\n } catch (e) {\n // Not good, this is a retryable error.\n this.errorCallback(e);\n }\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"promises.js","names":["handle: number","completer: (\n value: AsyncResultValue,\n prom: CompletablePromise<T>\n ) => Promise<void>","invocationIdPromise: Promise<InvocationId>","childs: Array<InternalRestatePromise<any>>","castedPromises: InternalRestatePromise<any>[]","foundContext: ContextImpl | undefined","inner: InternalRestatePromise<T>","promiseFactory: () => Promise<T>","settled: boolean","coreVm: vm.WasmVM","inputPump: InputPump","outputPump: OutputPump","runClosuresTracker: RunClosuresTracker","errorCallback: (e: any) => void"],"sources":["../src/promises.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2025 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type {\n RestatePromise,\n InvocationId,\n InvocationPromise,\n} from \"./context.js\";\nimport type * as vm from \"./endpoint/handlers/vm/sdk_shared_core_wasm_bindings.js\";\nimport {\n CancelledError,\n RestateError,\n TerminalError,\n TimeoutError,\n} from \"./types/errors.js\";\nimport { CompletablePromise } from \"./utils/completable_promise.js\";\nimport type { ContextImpl, RunClosuresTracker } from \"./context_impl.js\";\nimport { setImmediate } from \"node:timers/promises\";\nimport type { InputPump, OutputPump } from \"./io.js\";\nimport type { Duration } from \"@restatedev/restate-sdk-core\";\n\n// A promise that is never completed\nexport function pendingPromise<T>(): Promise<T> {\n return new Promise<T>(() => {});\n}\n\n// ------ Restate promises ------\n// These promises are \"proxy promises\" that will be handed over to the user,\n// and moved forward by the PromiseExecutor below when the user awaits on them.\n\n/**\n * Returns `true` if the given value is a {@link RestatePromise}.\n *\n * Use this for runtime type detection when you need to distinguish Restate promises\n * from regular promises, e.g. for overload resolution.\n */\nexport function isRestatePromise<T>(p: Promise<T>): p is RestatePromise<T> {\n return p instanceof InternalRestatePromise;\n}\n\nenum PromiseState {\n COMPLETED,\n NOT_COMPLETED,\n}\n\nexport abstract class InternalRestatePromise<T> implements RestatePromise<T> {\n abstract then<TResult1, TResult2>(\n onfulfilled:\n | ((value: T) => PromiseLike<TResult1> | TResult1)\n | undefined\n | null,\n onrejected:\n | ((reason: any) => PromiseLike<TResult2> | TResult2)\n | undefined\n | null\n ): Promise<TResult1 | TResult2>;\n abstract catch<TResult>(\n onrejected:\n | ((reason: any) => PromiseLike<TResult> | TResult)\n | undefined\n | null\n ): Promise<T | TResult>;\n abstract finally(onfinally: (() => void) | undefined | null): Promise<T>;\n\n abstract map<U>(\n mapper: (value?: T, failure?: TerminalError) => U\n ): RestatePromise<U>;\n abstract orTimeout(millis: Duration | number): RestatePromise<T>;\n\n abstract tryCancel(): void;\n abstract tryComplete(): Promise<void>;\n abstract uncompletedLeaves(): Array<number>;\n abstract publicPromise(): Promise<T>;\n\n abstract readonly [Symbol.toStringTag]: string;\n}\n\nexport type AsyncResultValue =\n | \"Empty\"\n | { Success: Uint8Array }\n | { Failure: vm.WasmFailure }\n | { StateKeys: string[] }\n | { InvocationId: string };\n\nconst RESTATE_CTX_SYMBOL = Symbol(\"restateContext\");\n\nfunction extractContext(n: any): ContextImpl | undefined {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return n[RESTATE_CTX_SYMBOL] as ContextImpl | undefined;\n}\n\nabstract class BaseRestatePromise<T> extends InternalRestatePromise<T> {\n [RESTATE_CTX_SYMBOL]: ContextImpl;\n private pollingPromise?: Promise<any>;\n private cancelPromise: CompletablePromise<any> = new CompletablePromise();\n\n protected constructor(ctx: ContextImpl) {\n super();\n this[RESTATE_CTX_SYMBOL] = ctx;\n }\n\n // --- Promise methods\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n this.pollingPromise =\n this.pollingPromise ||\n this[RESTATE_CTX_SYMBOL].promisesExecutor\n .doProgress(this)\n .catch(() => {});\n return this.publicPromiseOrCancelPromise().then(onfulfilled, onrejected);\n }\n\n catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null\n ): Promise<T | TResult> {\n this.pollingPromise =\n this.pollingPromise ||\n this[RESTATE_CTX_SYMBOL].promisesExecutor\n .doProgress(this)\n .catch(() => {});\n return this.publicPromiseOrCancelPromise().catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n this.pollingPromise =\n this.pollingPromise ||\n this[RESTATE_CTX_SYMBOL].promisesExecutor\n .doProgress(this)\n .catch(() => {});\n return this.publicPromiseOrCancelPromise().finally(onfinally);\n }\n\n private publicPromiseOrCancelPromise(): Promise<T> {\n return Promise.race([\n this.cancelPromise.promise as Promise<T>,\n this.publicPromise(),\n ]);\n }\n\n // --- RestatePromise methods\n\n orTimeout(duration: number | Duration): RestatePromise<T> {\n return new CombinatorRestatePromise(\n this[RESTATE_CTX_SYMBOL],\n ([thisPromise, sleepPromise]) => {\n return new Promise((resolve, reject) => {\n thisPromise!.then(resolve, reject);\n sleepPromise!.then(() => {\n reject(new TimeoutError());\n }, reject);\n });\n },\n [\n this,\n this[RESTATE_CTX_SYMBOL].sleep(duration) as InternalRestatePromise<any>,\n ]\n ) as RestatePromise<T>;\n }\n\n map<U>(mapper: (value?: T, failure?: TerminalError) => U): RestatePromise<U> {\n return new MappedRestatePromise(this[RESTATE_CTX_SYMBOL], this, mapper);\n }\n\n tryCancel() {\n this.cancelPromise.reject(new CancelledError());\n }\n\n abstract override tryComplete(): Promise<void>;\n\n abstract override uncompletedLeaves(): Array<number>;\n\n abstract override publicPromise(): Promise<T>;\n\n abstract override [Symbol.toStringTag]: string;\n}\n\nexport class SingleRestatePromise<T> extends BaseRestatePromise<T> {\n private state: PromiseState = PromiseState.NOT_COMPLETED;\n private completablePromise: CompletablePromise<T> = new CompletablePromise();\n\n constructor(\n ctx: ContextImpl,\n readonly handle: number,\n private readonly completer: (\n value: AsyncResultValue,\n prom: CompletablePromise<T>\n ) => Promise<void>\n ) {\n super(ctx);\n }\n\n uncompletedLeaves(): number[] {\n return this.state === PromiseState.COMPLETED ? [] : [this.handle];\n }\n\n async tryComplete(): Promise<void> {\n if (this.state === PromiseState.COMPLETED) {\n return;\n }\n const notification = this[RESTATE_CTX_SYMBOL].coreVm.take_notification(\n this.handle\n );\n if (notification === \"NotReady\") {\n return;\n }\n this.state = PromiseState.COMPLETED;\n await this.completer(notification, this.completablePromise);\n }\n\n publicPromise(): Promise<T> {\n return this.completablePromise.promise;\n }\n\n isCompleted(): boolean {\n return this.state === PromiseState.COMPLETED;\n }\n\n readonly [Symbol.toStringTag] = \"RestateSinglePromise\";\n}\n\nexport class InvocationRestatePromise<T>\n extends SingleRestatePromise<T>\n implements InvocationPromise<T>\n{\n constructor(\n ctx: ContextImpl,\n handle: number,\n completer: (\n value: AsyncResultValue,\n prom: CompletablePromise<T>\n ) => Promise<void>,\n private readonly invocationIdPromise: Promise<InvocationId>\n ) {\n super(ctx, handle, completer);\n }\n\n get invocationId(): Promise<InvocationId> {\n return this.invocationIdPromise;\n }\n}\n\nexport class CombinatorRestatePromise extends BaseRestatePromise<any> {\n private state: PromiseState = PromiseState.NOT_COMPLETED;\n private readonly combinatorPromise: Promise<any>;\n\n constructor(\n ctx: ContextImpl,\n combinatorConstructor: (promises: Promise<any>[]) => Promise<any>,\n readonly childs: Array<InternalRestatePromise<any>>\n ) {\n super(ctx);\n this.combinatorPromise = combinatorConstructor(\n childs.map((p) => p.publicPromise())\n ).finally(() => {\n this.state = PromiseState.COMPLETED;\n });\n }\n\n // Used by static methods of RestatePromise\n public static fromPromises<T extends readonly RestatePromise<unknown>[]>(\n combinatorConstructor: (promises: Promise<any>[]) => Promise<any>,\n promises: T\n ): RestatePromise<unknown> {\n const castedPromises: InternalRestatePromise<any>[] = [];\n let foundContext: ContextImpl | undefined = undefined;\n\n for (const [idx, promise] of promises.entries()) {\n if (!isRestatePromise(promise)) {\n throw new Error(\n `Promise index ${idx} used inside the combinator is not an instance of RestatePromise. This is not supported.`\n );\n } else if (foundContext === undefined) {\n foundContext = extractContext(promise);\n } else {\n const thisContext = extractContext(promise);\n if (thisContext !== undefined && thisContext !== foundContext) {\n throw new Error(\n \"You're mixing up RestatePromises from different RestateContext. This is not supported.\"\n );\n }\n }\n castedPromises.push(promise as InternalRestatePromise<any>);\n }\n\n if (foundContext === undefined) {\n // The only situation where this can happen is when the combined promise contains only ConstRestatePromise as children.\n // In this case, just return back a nice and clean ConstRestatePromise.\n // There is a specific workaround for the funky interface of Promise.race, inside the RestatePromise.race factory method.\n return ConstRestatePromise.fromPromise(\n combinatorConstructor(castedPromises),\n true\n );\n }\n\n return new CombinatorRestatePromise(\n foundContext,\n combinatorConstructor,\n castedPromises\n );\n }\n\n uncompletedLeaves(): number[] {\n return this.state === PromiseState.COMPLETED\n ? []\n : this.childs.flatMap((p) => p.uncompletedLeaves());\n }\n\n async tryComplete(): Promise<void> {\n await Promise.allSettled(this.childs.map((c) => c.tryComplete()));\n }\n\n publicPromise(): Promise<unknown> {\n return this.combinatorPromise;\n }\n\n readonly [Symbol.toStringTag] = \"RestateCombinatorPromise\";\n}\n\nexport class MappedRestatePromise<T, U> extends BaseRestatePromise<U> {\n private publicPromiseMapper: (\n value?: T,\n failure?: TerminalError\n ) => Promise<U>;\n // Memoized so the mapper fires at most once regardless of how many times\n // the promise is awaited / consumed via then/catch/finally/publicPromise.\n private _mappedPromise?: Promise<U>;\n\n constructor(\n ctx: ContextImpl,\n readonly inner: InternalRestatePromise<T>,\n mapper: (value?: T, failure?: TerminalError) => U\n ) {\n super(ctx);\n this.publicPromiseMapper = (value?: T, failure?: TerminalError) => {\n try {\n return Promise.resolve(mapper(value, failure));\n } catch (e) {\n if (e instanceof TerminalError) {\n return Promise.reject(e);\n } else {\n ctx.abortAttempt(e);\n return pendingPromise();\n }\n }\n };\n }\n\n async tryComplete(): Promise<void> {\n await this.inner.tryComplete();\n }\n\n uncompletedLeaves(): number[] {\n return this.inner.uncompletedLeaves();\n }\n\n publicPromise(): Promise<U> {\n return (this._mappedPromise ??= this.buildMappedPromise());\n }\n\n private buildMappedPromise(): Promise<U> {\n const promiseMapper = this.publicPromiseMapper;\n return this.inner.publicPromise().then(\n (t) => promiseMapper(t, undefined),\n (error) => {\n if (error instanceof RestateError) {\n return promiseMapper(undefined, error);\n } else {\n // Something else, just re-throw it\n throw error;\n }\n }\n );\n }\n\n readonly [Symbol.toStringTag] = \"RestateMappedPromise\";\n}\n\nexport class ConstRestatePromise<T> extends InternalRestatePromise<T> {\n private _constPromise?: Promise<T>;\n\n private constructor(\n // Factory for the underlying promise. Called at most once, memoized in\n // `_constPromise`.\n //\n // This way `map` is lazy, making it deterministically invoked on await points.\n private readonly promiseFactory: () => Promise<T>,\n private readonly settled: boolean\n ) {\n super();\n }\n\n private get constPromise(): Promise<T> {\n return (this._constPromise ??= this.promiseFactory());\n }\n\n static resolve<T>(value: T): ConstRestatePromise<Awaited<T>> {\n return new ConstRestatePromise(() => Promise.resolve(value), true);\n }\n\n static reject<T = never>(reason: TerminalError): ConstRestatePromise<T> {\n return new ConstRestatePromise<T>(() => Promise.reject(reason), true);\n }\n\n static pending<T>(): ConstRestatePromise<T> {\n return new ConstRestatePromise<T>(() => pendingPromise<T>(), false);\n }\n\n static fromPromise<T>(\n promise: Promise<T>,\n settled: boolean\n ): ConstRestatePromise<T> {\n return new ConstRestatePromise(() => promise, settled);\n }\n\n // --- Promise methods\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n return this.constPromise.then(onfulfilled, onrejected);\n }\n\n catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null\n ): Promise<T | TResult> {\n return this.constPromise.catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n return this.constPromise.finally(onfinally);\n }\n\n // --- RestatePromise methods\n\n orTimeout(): RestatePromise<T> {\n if (this.settled) return this;\n return ConstRestatePromise.reject(new TimeoutError());\n }\n\n map<U>(mapper: (value?: T, failure?: TerminalError) => U): RestatePromise<U> {\n if (!this.settled) return this as unknown as RestatePromise<U>;\n const selfConstPromise = this.constPromise;\n return new ConstRestatePromise<U>(\n () =>\n selfConstPromise.then(\n (value) => mapper(value, undefined),\n (reason) => mapper(undefined, reason as TerminalError)\n ),\n this.settled\n );\n }\n\n tryCancel() {}\n\n publicPromise(): Promise<T> {\n return this.constPromise;\n }\n\n tryComplete(): Promise<void> {\n return Promise.resolve();\n }\n\n uncompletedLeaves(): Array<number> {\n return [];\n }\n\n readonly [Symbol.toStringTag] = \"ConstRestatePromise\";\n}\n\n/**\n * Promises executor, gluing VM with I/O and Promises given to user space.\n */\nexport class PromisesExecutor {\n constructor(\n private readonly coreVm: vm.WasmVM,\n private readonly inputPump: InputPump,\n private readonly outputPump: OutputPump,\n private readonly runClosuresTracker: RunClosuresTracker,\n private readonly errorCallback: (e: any) => void\n ) {}\n\n async doProgress(restatePromise: InternalRestatePromise<unknown>) {\n // Only the first time try process output\n await this.outputPump.awaitNextProgress();\n await this.doProgressInner(restatePromise);\n }\n\n private async doProgressInner(\n restatePromise: InternalRestatePromise<unknown>\n ) {\n // Try complete the promise\n try {\n await restatePromise.tryComplete();\n } catch (e) {\n // This can happen if either take_notification throws an exception or completer throws an exception.\n // This could either happen for a deserialization issue, or for an SDK bug, but we cover them here.\n this.errorCallback(e);\n return Promise.resolve();\n }\n\n // tl;dr don't touch this, or you can break combineable promises,\n // slinkydeveloper won't be happy about it\n //\n // The reason for this setTimeout is that we need to enqueue the polling after\n // we eventually resolve some promises. This is especially crucial for RestateCombinatorPromise\n // as it flips the completed state using .finally() on the combinator.\n return setImmediate().then(async () => {\n try {\n // Invoke do progress on the vm\n const handles = restatePromise.uncompletedLeaves();\n if (handles.length === 0) {\n // Completed, we're good!\n return;\n }\n const doProgressResult = this.coreVm.do_progress(\n new Uint32Array(handles)\n );\n\n if (doProgressResult === \"AnyCompleted\") {\n // Next recursion will cause the promise to do some progress\n } else if (\n doProgressResult === \"ReadFromInput\" ||\n doProgressResult === \"WaitingPendingRun\"\n ) {\n // The shared-core now can't make progress without \"external progress\".\n //\n // There are really 3 situations here:\n // * Input is still open, and a run is being executed.\n // Both reading from input or proposing a run completion causes the invocation to make progress.\n // * Input is still open, there is no run being executed.\n // Only reading from input causes the invocation to make progress.\n // * Input is closed, a run is being executed.\n // Only proposing a run completion causes the invocation to make progress.\n\n // In this scenario, we might need to write some stuff out which might be in the shared-core buffer.\n await this.outputPump.awaitNextProgress();\n\n await Promise.race([\n this.inputPump.awaitNextProgress(),\n this.runClosuresTracker.awaitNextCompletedRun(),\n ]);\n } else if (doProgressResult === \"CancelSignalReceived\") {\n restatePromise.tryCancel();\n return;\n } else {\n // We need to execute a run closure\n this.runClosuresTracker.executeRun(doProgressResult.ExecuteRun);\n // Let the run context switch, then come back to this flow.\n await setImmediate();\n }\n\n // Recursion\n await this.doProgressInner(restatePromise);\n } catch (e) {\n // Not good, this is a retryable error.\n this.errorCallback(e);\n }\n });\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@restatedev/restate-sdk-cloudflare-workers",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Typescript SDK for Restate",
|
|
5
5
|
"author": "Restate Developers",
|
|
6
6
|
"email": "code@restate.dev",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@restatedev/restate-sdk-core": "1.
|
|
38
|
+
"@restatedev/restate-sdk-core": "1.14.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/aws-lambda": "^8.10.115",
|
|
42
|
-
"@restatedev/restate-sdk": "1.
|
|
42
|
+
"@restatedev/restate-sdk": "1.14.0"
|
|
43
43
|
},
|
|
44
44
|
"typesVersions": {
|
|
45
45
|
"*": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "turbo run _build --filter={.}...",
|
|
53
|
-
"_build": "./patch_sdk_cf_workers.sh",
|
|
53
|
+
"_build": "rm -rf dist && ./patch_sdk_cf_workers.sh && rm -f dist/endpoint/handlers/vm/.gitignore",
|
|
54
54
|
"clean": "rm -rf dist *.tsbuildinfo .turbo",
|
|
55
55
|
"check:exports": "turbo run _check:exports --filter={.}...",
|
|
56
56
|
"_check:exports": "attw --pack .",
|