@restatedev/restate-sdk-cloudflare-workers 1.10.4 → 1.11.1
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/context_impl.cjs +17 -6
- package/dist/context_impl.js +17 -6
- package/dist/context_impl.js.map +1 -1
- package/dist/endpoint/endpoint.cjs +2 -2
- package/dist/endpoint/endpoint.js +2 -2
- package/dist/endpoint/fetch_endpoint.cjs +2 -2
- package/dist/endpoint/fetch_endpoint.js +2 -2
- package/dist/endpoint/fetch_endpoint.js.map +1 -1
- package/dist/endpoint/handlers/core_logging.cjs +52 -0
- package/dist/endpoint/handlers/core_logging.js +51 -0
- package/dist/endpoint/handlers/core_logging.js.map +1 -0
- package/dist/endpoint/handlers/discovery.cjs +58 -0
- package/dist/endpoint/handlers/discovery.js +59 -0
- package/dist/endpoint/handlers/discovery.js.map +1 -0
- package/dist/endpoint/handlers/fetch.cjs +23 -11
- package/dist/endpoint/handlers/fetch.js +24 -11
- package/dist/endpoint/handlers/fetch.js.map +1 -1
- package/dist/endpoint/handlers/generic.cjs +167 -253
- package/dist/endpoint/handlers/generic.js +166 -249
- package/dist/endpoint/handlers/generic.js.map +1 -1
- package/dist/endpoint/handlers/lambda.cjs +64 -61
- package/dist/endpoint/handlers/lambda.js +64 -60
- package/dist/endpoint/handlers/lambda.js.map +1 -1
- package/dist/endpoint/handlers/utils.cjs +51 -0
- package/dist/endpoint/handlers/utils.js +48 -0
- package/dist/endpoint/handlers/utils.js.map +1 -0
- package/dist/endpoint/handlers/vm/sdk_shared_core_wasm_bindings.d.ts +13 -13
- package/dist/endpoint/handlers/vm/sdk_shared_core_wasm_bindings_bg.js +20 -20
- package/dist/endpoint/handlers/vm/sdk_shared_core_wasm_bindings_bg.wasm +0 -0
- package/dist/endpoint/lambda_endpoint.cjs +2 -2
- package/dist/endpoint/lambda_endpoint.js +2 -2
- package/dist/endpoint/lambda_endpoint.js.map +1 -1
- package/dist/endpoint/node_endpoint.cjs +41 -41
- package/dist/endpoint/node_endpoint.js +41 -40
- package/dist/endpoint/node_endpoint.js.map +1 -1
- package/dist/io.cjs +2 -2
- package/dist/io.js +2 -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/types/errors.cjs +2 -0
- package/dist/types/errors.d.cts +8 -0
- package/dist/types/errors.d.cts.map +1 -1
- package/dist/types/errors.d.ts +8 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +2 -0
- package/dist/types/errors.js.map +1 -1
- package/package.json +3 -3
- package/dist/utils/streams.cjs +0 -14
- package/dist/utils/streams.js +0 -13
- package/dist/utils/streams.js.map +0 -1
|
@@ -1,49 +1,28 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
-
const require_errors = require('../../types/errors.cjs');
|
|
3
|
-
const require_rpc = require('../../types/rpc.cjs');
|
|
4
|
-
const require_components = require('../components.cjs');
|
|
5
|
-
const require_user_agent = require('../../user_agent.cjs');
|
|
6
|
-
const require_streams = require('../../utils/streams.cjs');
|
|
7
|
-
const require_completable_promise = require('../../utils/completable_promise.cjs');
|
|
8
2
|
const require_logger_transport = require('../../logging/logger_transport.cjs');
|
|
9
|
-
const require_logger = require('../../logging/logger.cjs');
|
|
10
3
|
const require_console_logger_transport = require('../../logging/console_logger_transport.cjs');
|
|
4
|
+
const require_core_logging = require('./core_logging.cjs');
|
|
11
5
|
const require_sdk_shared_core_wasm_bindings = require('./vm/sdk_shared_core_wasm_bindings.cjs');
|
|
6
|
+
const require_errors = require('../../types/errors.cjs');
|
|
7
|
+
const require_rpc = require('../../types/rpc.cjs');
|
|
8
|
+
const require_completable_promise = require('../../utils/completable_promise.cjs');
|
|
12
9
|
const require_context_impl = require('../../context_impl.cjs');
|
|
10
|
+
const require_components = require('../components.cjs');
|
|
11
|
+
const require_logger = require('../../logging/logger.cjs');
|
|
12
|
+
const require_user_agent = require('../../user_agent.cjs');
|
|
13
|
+
const require_utils = require('./utils.cjs');
|
|
14
|
+
const require_discovery = require('./discovery.cjs');
|
|
13
15
|
let __restatedev_restate_sdk_core = require("@restatedev/restate-sdk-core");
|
|
14
16
|
__restatedev_restate_sdk_core = require_rolldown_runtime.__toESM(__restatedev_restate_sdk_core);
|
|
15
|
-
let node_stream_web = require("node:stream/web");
|
|
16
|
-
node_stream_web = require_rolldown_runtime.__toESM(node_stream_web);
|
|
17
17
|
|
|
18
18
|
//#region src/endpoint/handlers/generic.ts
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const ENDPOINT_MANIFEST_V4 = "application/vnd.restate.endpointmanifest.v4+json";
|
|
22
|
-
function tryCreateContextualLogger(loggerTransport, url, headers, additionalContext) {
|
|
23
|
-
try {
|
|
24
|
-
const path = new URL(url, "https://example.com").pathname;
|
|
25
|
-
const parsed = require_components.parseUrlComponents(path);
|
|
26
|
-
if (parsed.type !== "invoke") return;
|
|
27
|
-
const invocationId = invocationIdFromHeaders(headers);
|
|
28
|
-
return require_logger.createLogger(loggerTransport, require_logger_transport.LogSource.SYSTEM, new require_logger_transport.LoggerContext(invocationId, parsed.componentName, parsed.handlerName, void 0, void 0, additionalContext));
|
|
29
|
-
} catch {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function invocationIdFromHeaders(headers) {
|
|
34
|
-
const invocationIdHeader = headers["x-restate-invocation-id"];
|
|
35
|
-
return typeof invocationIdHeader === "string" ? invocationIdHeader : Array.isArray(invocationIdHeader) ? invocationIdHeader[0] ?? "unknown id" : "unknown id";
|
|
19
|
+
function createRestateHandler(endpoint, protocolMode, additionalDiscoveryFields) {
|
|
20
|
+
return new RestateHandlerImpl(endpoint, protocolMode, additionalDiscoveryFields);
|
|
36
21
|
}
|
|
37
22
|
/**
|
|
38
|
-
* This is
|
|
39
|
-
* It supports both request-reply mode and bidirectional streaming mode.
|
|
40
|
-
*
|
|
41
|
-
* An individual handler will have to convert the shape of the incoming request
|
|
42
|
-
* to a RestateRequest, and then pass it to this handler, and eventually convert back
|
|
43
|
-
* the response.
|
|
44
|
-
* Different runtimes have slightly different shapes of the incoming request, and responses.
|
|
23
|
+
* This is the RestateHandler implementation
|
|
45
24
|
*/
|
|
46
|
-
var
|
|
25
|
+
var RestateHandlerImpl = class {
|
|
47
26
|
identityVerifier;
|
|
48
27
|
constructor(endpoint, protocolMode, additionalDiscoveryFields) {
|
|
49
28
|
this.endpoint = endpoint;
|
|
@@ -56,57 +35,31 @@ var GenericHandler = class {
|
|
|
56
35
|
}
|
|
57
36
|
require_sdk_shared_core_wasm_bindings.set_log_level(restateLogLevelToWasmLogLevel(require_console_logger_transport.DEFAULT_CONSOLE_LOGGER_LOG_LEVEL));
|
|
58
37
|
}
|
|
59
|
-
|
|
38
|
+
handle(request, context) {
|
|
60
39
|
try {
|
|
61
|
-
return
|
|
40
|
+
return this._handle(request, context);
|
|
62
41
|
} catch (e) {
|
|
63
42
|
const error = require_errors.ensureError(e);
|
|
64
|
-
(tryCreateContextualLogger(this.endpoint.loggerTransport, request.url, request.headers) ?? this.endpoint.rlog).error("Error while handling request: " + (error.stack ?? error.message));
|
|
65
|
-
return
|
|
43
|
+
(require_utils.tryCreateContextualLogger(this.endpoint.loggerTransport, request.url, request.headers) ?? this.endpoint.rlog).error("Error while handling request: " + (error.stack ?? error.message));
|
|
44
|
+
return require_utils.errorResponse(error instanceof require_errors.RestateError ? error.code : 500, error.message);
|
|
66
45
|
}
|
|
67
46
|
}
|
|
68
|
-
|
|
47
|
+
_handle(request, context) {
|
|
69
48
|
const path = new URL(request.url, "https://example.com").pathname;
|
|
70
49
|
const parsed = require_components.parseUrlComponents(path);
|
|
71
50
|
if (parsed.type === "unknown") {
|
|
72
51
|
const msg = `Invalid path. Allowed are /health, or /discover, or /invoke/SvcName/handlerName, but was: ${path}`;
|
|
73
52
|
this.endpoint.rlog.trace(msg);
|
|
74
|
-
return
|
|
53
|
+
return require_utils.errorResponse(404, msg);
|
|
75
54
|
}
|
|
76
|
-
if (parsed.type === "health") return {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"x-restate-server": require_user_agent.X_RESTATE_SERVER
|
|
81
|
-
},
|
|
82
|
-
statusCode: 200
|
|
83
|
-
};
|
|
55
|
+
if (parsed.type === "health") return require_utils.simpleResponse(200, {
|
|
56
|
+
"content-type": "application/text",
|
|
57
|
+
"x-restate-server": require_user_agent.X_RESTATE_SERVER
|
|
58
|
+
}, new TextEncoder().encode("OK"));
|
|
84
59
|
const error = this.validateConnectionSignature(path, request.headers);
|
|
85
60
|
if (error !== null) return error;
|
|
86
|
-
if (parsed.type === "discover") return
|
|
87
|
-
|
|
88
|
-
const errorMessage = "Missing content-type header";
|
|
89
|
-
this.endpoint.rlog.warn(errorMessage);
|
|
90
|
-
return this.toErrorResponse(415, errorMessage);
|
|
91
|
-
}
|
|
92
|
-
const service = this.endpoint.components.get(parsed.componentName);
|
|
93
|
-
if (!service) {
|
|
94
|
-
const msg = `No service found for URL: ${JSON.stringify(parsed)}`;
|
|
95
|
-
this.endpoint.rlog.error(msg);
|
|
96
|
-
return this.toErrorResponse(404, msg);
|
|
97
|
-
}
|
|
98
|
-
const handler = service?.handlerMatching(parsed);
|
|
99
|
-
if (!handler) {
|
|
100
|
-
const msg = `No service found for URL: ${JSON.stringify(parsed)}`;
|
|
101
|
-
this.endpoint.rlog.error(msg);
|
|
102
|
-
return this.toErrorResponse(404, msg);
|
|
103
|
-
}
|
|
104
|
-
if (!request.body) {
|
|
105
|
-
const msg = "The incoming message body was null";
|
|
106
|
-
this.endpoint.rlog.error(msg);
|
|
107
|
-
return this.toErrorResponse(400, msg);
|
|
108
|
-
}
|
|
109
|
-
return this.handleInvoke(service, handler, request.body, request.headers, request.extraArgs, request.abortSignal, context ?? {});
|
|
61
|
+
if (parsed.type === "discover") return require_discovery.handleDiscovery(this.endpoint, this.protocolMode, this.additionalDiscoveryFields, request.headers["accept"]);
|
|
62
|
+
return this.handleInvoke(parsed, request.headers, request.extraArgs, context ?? {});
|
|
110
63
|
}
|
|
111
64
|
validateConnectionSignature(path, headers) {
|
|
112
65
|
if (!this.identityVerifier) return null;
|
|
@@ -116,207 +69,170 @@ var GenericHandler = class {
|
|
|
116
69
|
return null;
|
|
117
70
|
} catch (e) {
|
|
118
71
|
this.endpoint.rlog.error(`Rejecting request as its JWT did not validate: ${e}`);
|
|
119
|
-
return
|
|
72
|
+
return require_utils.errorResponse(401, "Unauthorized");
|
|
120
73
|
}
|
|
121
74
|
}
|
|
122
|
-
|
|
123
|
-
|
|
75
|
+
handleInvoke(invokePathComponent, headers, extraArgs, additionalContext) {
|
|
76
|
+
if (typeof headers["content-type"] !== "string") {
|
|
77
|
+
const errorMessage = "Missing content-type header";
|
|
78
|
+
this.endpoint.rlog.warn(errorMessage);
|
|
79
|
+
return require_utils.errorResponse(415, errorMessage);
|
|
80
|
+
}
|
|
81
|
+
const service = this.endpoint.components.get(invokePathComponent.componentName);
|
|
82
|
+
if (!service) {
|
|
83
|
+
const msg = `No service found for URL: ${JSON.stringify(invokePathComponent)}`;
|
|
84
|
+
this.endpoint.rlog.error(msg);
|
|
85
|
+
return require_utils.errorResponse(404, msg);
|
|
86
|
+
}
|
|
87
|
+
const handler = service?.handlerMatching(invokePathComponent);
|
|
88
|
+
if (!handler) {
|
|
89
|
+
const msg = `No service found for URL: ${JSON.stringify(invokePathComponent)}`;
|
|
90
|
+
this.endpoint.rlog.error(msg);
|
|
91
|
+
return require_utils.errorResponse(404, msg);
|
|
92
|
+
}
|
|
93
|
+
return new RestateInvokeResponse(service, handler, headers, extraArgs, additionalContext, this.endpoint.journalValueCodec, this.endpoint.loggerTransport);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
var RestateInvokeResponse = class {
|
|
97
|
+
headers;
|
|
98
|
+
statusCode;
|
|
99
|
+
loggerId;
|
|
100
|
+
vmLogger;
|
|
101
|
+
coreVm;
|
|
102
|
+
constructor(service, handler, attemptHeaders, extraArgs, additionalContext, journalValueCodecInit, loggerTransport) {
|
|
103
|
+
this.service = service;
|
|
104
|
+
this.handler = handler;
|
|
105
|
+
this.attemptHeaders = attemptHeaders;
|
|
106
|
+
this.extraArgs = extraArgs;
|
|
107
|
+
this.additionalContext = additionalContext;
|
|
108
|
+
this.journalValueCodecInit = journalValueCodecInit;
|
|
109
|
+
this.loggerTransport = loggerTransport;
|
|
110
|
+
this.loggerId = Math.floor(Math.random() * 4294967295);
|
|
111
|
+
const isJournalCodecDefined = this.journalValueCodecInit !== void 0;
|
|
112
|
+
const vmHeaders = Object.entries(this.attemptHeaders).filter(([, v]) => v !== void 0).map(([k, v]) => new require_sdk_shared_core_wasm_bindings.WasmHeader(k, v instanceof Array ? v[0] : v));
|
|
113
|
+
this.coreVm = new require_sdk_shared_core_wasm_bindings.WasmVM(vmHeaders, restateLogLevelToWasmLogLevel(require_console_logger_transport.DEFAULT_CONSOLE_LOGGER_LOG_LEVEL), this.loggerId, isJournalCodecDefined);
|
|
114
|
+
const responseHead = this.coreVm.get_response_head();
|
|
115
|
+
this.statusCode = responseHead.status_code;
|
|
116
|
+
this.headers = responseHead.headers.reduce((headers, { key, value }) => ({
|
|
117
|
+
[key]: value,
|
|
118
|
+
...headers
|
|
119
|
+
}), { "x-restate-server": require_user_agent.X_RESTATE_SERVER });
|
|
120
|
+
this.vmLogger = require_logger.createLogger(this.loggerTransport, require_logger_transport.LogSource.JOURNAL, new require_logger_transport.LoggerContext(require_utils.invocationIdFromHeaders(this.attemptHeaders), this.service.name(), this.handler.name(), void 0, void 0, this.additionalContext));
|
|
121
|
+
}
|
|
122
|
+
async process({ inputReader, outputWriter, abortSignal }) {
|
|
123
|
+
abortSignal.addEventListener("abort", () => {
|
|
124
|
+
require_core_logging.destroyLogger(this.loggerId);
|
|
125
|
+
}, { once: true });
|
|
126
|
+
require_core_logging.registerLogger(this.loggerId, this.vmLogger);
|
|
127
|
+
const journalValueCodec = this.journalValueCodecInit ? await this.journalValueCodecInit : {
|
|
124
128
|
encode: (entry) => entry,
|
|
125
129
|
decode: (entry) => Promise.resolve(entry)
|
|
126
130
|
};
|
|
127
|
-
const
|
|
131
|
+
const invocationEndPromise = new require_completable_promise.CompletablePromise();
|
|
132
|
+
let ctx;
|
|
128
133
|
try {
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
const responseHead = coreVm.get_response_head();
|
|
132
|
-
const responseHeaders = responseHead.headers.reduce((headers$1, { key, value }) => ({
|
|
133
|
-
[key]: value,
|
|
134
|
-
...headers$1
|
|
135
|
-
}), { "x-restate-server": require_user_agent.X_RESTATE_SERVER });
|
|
136
|
-
invocationLoggers.set(loggerId, require_logger.createLogger(this.endpoint.loggerTransport, require_logger_transport.LogSource.JOURNAL, new require_logger_transport.LoggerContext(invocationIdFromHeaders(headers), service.name(), handler.name(), void 0, void 0, additionalContext)));
|
|
137
|
-
const inputReader = body.getReader();
|
|
138
|
-
abortSignal.addEventListener("abort", () => {
|
|
139
|
-
invocationLoggers.delete(loggerId);
|
|
140
|
-
inputReader.cancel();
|
|
141
|
-
}, { once: true });
|
|
142
|
-
while (!coreVm.is_ready_to_execute()) {
|
|
143
|
-
const nextValue = await inputReader.read();
|
|
144
|
-
if (nextValue.value !== void 0) coreVm.notify_input(nextValue.value);
|
|
145
|
-
if (nextValue.done) {
|
|
146
|
-
coreVm.notify_input_closed();
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
const input = coreVm.sys_input();
|
|
134
|
+
await bufferJournalReplayInCoreVm(this.coreVm, inputReader);
|
|
135
|
+
const input = this.coreVm.sys_input();
|
|
151
136
|
const invocationRequest = {
|
|
152
137
|
id: input.invocation_id,
|
|
153
|
-
headers: input.headers.reduce((headers
|
|
154
|
-
headers
|
|
155
|
-
return headers
|
|
138
|
+
headers: input.headers.reduce((headers, { key, value }) => {
|
|
139
|
+
headers.set(key, value);
|
|
140
|
+
return headers;
|
|
156
141
|
}, /* @__PURE__ */ new Map()),
|
|
157
|
-
attemptHeaders: Object.entries(
|
|
158
|
-
if (value !== void 0) headers
|
|
159
|
-
return headers
|
|
142
|
+
attemptHeaders: Object.entries(this.attemptHeaders).reduce((headers, [key, value]) => {
|
|
143
|
+
if (value !== void 0) headers.set(key, value instanceof Array ? value[0] : value);
|
|
144
|
+
return headers;
|
|
160
145
|
}, /* @__PURE__ */ new Map()),
|
|
161
146
|
body: input.input,
|
|
162
|
-
extraArgs,
|
|
147
|
+
extraArgs: this.extraArgs,
|
|
163
148
|
attemptCompletedSignal: abortSignal
|
|
164
149
|
};
|
|
165
|
-
const loggerContext = new require_logger_transport.LoggerContext(input.invocation_id, handler.component().name(), handler.name(), handler.kind() === require_rpc.HandlerKind.SERVICE ? void 0 : input.key, invocationRequest, additionalContext);
|
|
166
|
-
const ctxLogger = require_logger.createLogger(this.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (!coreVm.is_processing()) vmLogger.info("Replaying invocation.");
|
|
170
|
-
else vmLogger.info("Starting invocation.");
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
coreVm.sys_end();
|
|
178
|
-
vmLogger.info("Invocation completed successfully.");
|
|
179
|
-
}).catch((e) => {
|
|
180
|
-
const error = require_errors.ensureError(e, service.options?.asTerminalError);
|
|
181
|
-
require_errors.logError(vmLogger, error);
|
|
182
|
-
if (error instanceof require_errors.TerminalError) {
|
|
183
|
-
coreVm.sys_write_output_failure({
|
|
184
|
-
code: error.code,
|
|
185
|
-
message: error.message,
|
|
186
|
-
metadata: []
|
|
187
|
-
});
|
|
188
|
-
coreVm.sys_end();
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
throw error;
|
|
192
|
-
}).catch((e) => {
|
|
193
|
-
const error = require_errors.ensureError(e);
|
|
194
|
-
if (error instanceof require_errors.RetryableError) coreVm.notify_error_with_delay_override(error.message, error.stack, error.retryAfter !== void 0 ? BigInt((0, __restatedev_restate_sdk_core.millisOrDurationToMillis)(error.retryAfter)) : void 0);
|
|
195
|
-
else coreVm.notify_error(error.message, error.stack);
|
|
196
|
-
}).finally(() => {
|
|
197
|
-
invocationEndPromise.resolve();
|
|
198
|
-
});
|
|
199
|
-
invocationEndPromise.promise.then(async () => {
|
|
200
|
-
let nextOutput = coreVm.take_output();
|
|
201
|
-
while (nextOutput !== null && nextOutput !== void 0) {
|
|
202
|
-
await outputWriter.write(nextOutput);
|
|
203
|
-
nextOutput = coreVm.take_output();
|
|
204
|
-
}
|
|
205
|
-
let inputClosed = false;
|
|
206
|
-
while (!inputClosed) try {
|
|
207
|
-
inputClosed = (await inputReader.read()).done;
|
|
208
|
-
} catch (e) {
|
|
209
|
-
inputClosed = true;
|
|
210
|
-
}
|
|
211
|
-
await outputWriter.close();
|
|
212
|
-
}).finally(() => {
|
|
213
|
-
invocationLoggers.delete(loggerId);
|
|
214
|
-
}).catch(() => {});
|
|
215
|
-
return {
|
|
216
|
-
headers: responseHeaders,
|
|
217
|
-
statusCode: responseHead.status_code,
|
|
218
|
-
body: responseTransformStream.readable
|
|
219
|
-
};
|
|
220
|
-
} catch (error) {
|
|
221
|
-
invocationLoggers.delete(loggerId);
|
|
222
|
-
throw error;
|
|
150
|
+
const loggerContext = new require_logger_transport.LoggerContext(input.invocation_id, this.handler.component().name(), this.handler.name(), this.handler.kind() === require_rpc.HandlerKind.SERVICE ? void 0 : input.key, invocationRequest, this.additionalContext);
|
|
151
|
+
const ctxLogger = require_logger.createLogger(this.loggerTransport, require_logger_transport.LogSource.USER, loggerContext, () => !this.coreVm.is_processing());
|
|
152
|
+
this.vmLogger = require_logger.createLogger(this.loggerTransport, require_logger_transport.LogSource.JOURNAL, loggerContext);
|
|
153
|
+
require_core_logging.registerLogger(this.loggerId, this.vmLogger);
|
|
154
|
+
if (!this.coreVm.is_processing()) this.vmLogger.info("Replaying invocation.");
|
|
155
|
+
else this.vmLogger.info("Starting invocation.");
|
|
156
|
+
ctx = new require_context_impl.ContextImpl(this.coreVm, input, ctxLogger, this.handler.kind(), this.vmLogger, invocationRequest, invocationEndPromise, inputReader, outputWriter, journalValueCodec, this.service.options?.serde, this.service.options?.asTerminalError);
|
|
157
|
+
} catch (e) {
|
|
158
|
+
const error = require_errors.ensureError(e);
|
|
159
|
+
this.coreVm.notify_error(error.message, error.message);
|
|
160
|
+
await flushAndClose(this.coreVm, this.vmLogger, inputReader, outputWriter);
|
|
161
|
+
return;
|
|
223
162
|
}
|
|
163
|
+
startUserHandler(ctx, this.service, this.handler, journalValueCodec).finally(() => {
|
|
164
|
+
invocationEndPromise.resolve();
|
|
165
|
+
});
|
|
166
|
+
await invocationEndPromise.promise;
|
|
167
|
+
await flushAndClose(this.coreVm, this.vmLogger, inputReader, outputWriter);
|
|
224
168
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (acceptVersionsString.includes(ENDPOINT_MANIFEST_V4)) manifestVersion = 4;
|
|
233
|
-
else if (acceptVersionsString.includes(ENDPOINT_MANIFEST_V3)) manifestVersion = 3;
|
|
234
|
-
else if (acceptVersionsString.includes(ENDPOINT_MANIFEST_V2)) manifestVersion = 2;
|
|
235
|
-
else {
|
|
236
|
-
const errorMessage = `Unsupported service discovery protocol version '${acceptVersionsString}'`;
|
|
237
|
-
this.endpoint.rlog.warn(errorMessage);
|
|
238
|
-
return this.toErrorResponse(415, errorMessage);
|
|
239
|
-
}
|
|
240
|
-
const discovery = {
|
|
241
|
-
...this.endpoint.discoveryMetadata,
|
|
242
|
-
...this.additionalDiscoveryFields,
|
|
243
|
-
protocolMode: this.protocolMode
|
|
244
|
-
};
|
|
245
|
-
const checkUnsupportedFeature = (obj, ...fields) => {
|
|
246
|
-
for (const field of fields) if (field in obj && obj[field] !== void 0) return this.toErrorResponse(500, `The code uses the new discovery feature '${String(field)}' but the runtime doesn't support it yet (discovery protocol negotiated version ${manifestVersion}). Either remove the usage of this feature, or upgrade the runtime.`);
|
|
247
|
-
};
|
|
248
|
-
if (manifestVersion < 3) for (const service of discovery.services) {
|
|
249
|
-
const error = checkUnsupportedFeature(service, "journalRetention", "idempotencyRetention", "inactivityTimeout", "abortTimeout", "enableLazyState", "ingressPrivate");
|
|
250
|
-
if (error !== void 0) return error;
|
|
251
|
-
for (const handler of service.handlers) {
|
|
252
|
-
const error$1 = checkUnsupportedFeature(handler, "journalRetention", "idempotencyRetention", "workflowCompletionRetention", "inactivityTimeout", "abortTimeout", "enableLazyState", "ingressPrivate");
|
|
253
|
-
if (error$1 !== void 0) return error$1;
|
|
254
|
-
}
|
|
169
|
+
};
|
|
170
|
+
async function bufferJournalReplayInCoreVm(coreVm, inputReader) {
|
|
171
|
+
while (!coreVm.is_ready_to_execute()) {
|
|
172
|
+
const nextValue = await inputReader.next();
|
|
173
|
+
if (nextValue.done) {
|
|
174
|
+
coreVm.notify_input_closed();
|
|
175
|
+
break;
|
|
255
176
|
}
|
|
256
|
-
if (
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
177
|
+
if (nextValue.value !== void 0) coreVm.notify_input(nextValue.value);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function startUserHandler(ctx, service, handler, journalValueCodec) {
|
|
181
|
+
try {
|
|
182
|
+
try {
|
|
183
|
+
const decodedInput = await journalValueCodec.decode(ctx.request().body).catch((e) => Promise.reject(new require_errors.TerminalError(`Failed to decode input using journal value codec: ${require_errors.ensureError(e).message}`, { errorCode: 400 })));
|
|
184
|
+
const output = await handler.invoke(ctx, decodedInput);
|
|
185
|
+
const encodedOutput = journalValueCodec.encode(output);
|
|
186
|
+
ctx.coreVm.sys_write_output_success(encodedOutput);
|
|
187
|
+
ctx.coreVm.sys_end();
|
|
188
|
+
ctx.vmLogger.info("Invocation completed successfully.");
|
|
189
|
+
} catch (e) {
|
|
190
|
+
const error = require_errors.ensureError(e, service.options?.asTerminalError);
|
|
191
|
+
require_errors.logError(ctx.vmLogger, error);
|
|
192
|
+
if (error instanceof require_errors.TerminalError) {
|
|
193
|
+
ctx.coreVm.sys_write_output_failure({
|
|
194
|
+
code: error.code,
|
|
195
|
+
message: error.message,
|
|
196
|
+
metadata: Object.entries(error.metadata ?? {}).map(([key, value]) => ({
|
|
197
|
+
key,
|
|
198
|
+
value
|
|
199
|
+
}))
|
|
200
|
+
});
|
|
201
|
+
ctx.coreVm.sys_end();
|
|
202
|
+
return;
|
|
265
203
|
}
|
|
204
|
+
throw error;
|
|
266
205
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"x-restate-server": require_user_agent.X_RESTATE_SERVER
|
|
272
|
-
},
|
|
273
|
-
statusCode: 200,
|
|
274
|
-
body: require_streams.OnceStream(new TextEncoder().encode(body))
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
toErrorResponse(code, message) {
|
|
278
|
-
return {
|
|
279
|
-
headers: {
|
|
280
|
-
"content-type": "application/json",
|
|
281
|
-
"x-restate-server": require_user_agent.X_RESTATE_SERVER
|
|
282
|
-
},
|
|
283
|
-
statusCode: code,
|
|
284
|
-
body: require_streams.OnceStream(new TextEncoder().encode(JSON.stringify({ message })))
|
|
285
|
-
};
|
|
206
|
+
} catch (e) {
|
|
207
|
+
const error = require_errors.ensureError(e);
|
|
208
|
+
if (error instanceof require_errors.RetryableError) ctx.coreVm.notify_error_with_delay_override(error.message, error.stack, error.retryAfter !== void 0 ? BigInt((0, __restatedev_restate_sdk_core.millisOrDurationToMillis)(error.retryAfter)) : void 0);
|
|
209
|
+
else ctx.coreVm.notify_error(error.message, error.stack);
|
|
286
210
|
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* The shared core propagates logs to the SDK invoking this method.
|
|
292
|
-
* When possible it provides an invocationId, which is used to access the registered invocationLoggers, that should contain the logger per invocation id.
|
|
293
|
-
*/
|
|
294
|
-
function vm_log(level, strBytes, loggerId) {
|
|
211
|
+
}
|
|
212
|
+
async function flushAndClose(coreVm, vmLogger, inputReader, outputWriter) {
|
|
213
|
+
let inputClosed = false;
|
|
295
214
|
try {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
215
|
+
let nextOutput = coreVm.take_output();
|
|
216
|
+
while (nextOutput !== null && nextOutput !== void 0) {
|
|
217
|
+
await outputWriter.write(nextOutput);
|
|
218
|
+
nextOutput = coreVm.take_output();
|
|
219
|
+
}
|
|
220
|
+
while (!inputClosed) try {
|
|
221
|
+
inputClosed = (await inputReader.next()).done ?? false;
|
|
222
|
+
} catch (e) {
|
|
223
|
+
inputClosed = true;
|
|
224
|
+
}
|
|
225
|
+
await outputWriter.close();
|
|
304
226
|
} catch (e) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
227
|
+
const error = require_errors.ensureError(e);
|
|
228
|
+
const abortErrorOnWrite = isAbortErrorOnWrite(error);
|
|
229
|
+
if (inputClosed && abortErrorOnWrite) return;
|
|
230
|
+
if (abortErrorOnWrite) vmLogger.error("Got abort error from connection: " + error.message + "\nThis might indicate that:\n* The restate-server aborted the connection after hitting the 'abort-timeout'\n* The connection with the restate-server was lost\n\nPlease check the invocation in the Restate UI for more details.");
|
|
231
|
+
else vmLogger.error("Error while handling request: " + (error.stack ?? error.message));
|
|
310
232
|
}
|
|
311
233
|
}
|
|
312
|
-
function
|
|
313
|
-
|
|
314
|
-
case require_sdk_shared_core_wasm_bindings.LogLevel.TRACE: return require_logger_transport.RestateLogLevel.TRACE;
|
|
315
|
-
case require_sdk_shared_core_wasm_bindings.LogLevel.DEBUG: return require_logger_transport.RestateLogLevel.DEBUG;
|
|
316
|
-
case require_sdk_shared_core_wasm_bindings.LogLevel.INFO: return require_logger_transport.RestateLogLevel.INFO;
|
|
317
|
-
case require_sdk_shared_core_wasm_bindings.LogLevel.WARN: return require_logger_transport.RestateLogLevel.WARN;
|
|
318
|
-
case require_sdk_shared_core_wasm_bindings.LogLevel.ERROR: return require_logger_transport.RestateLogLevel.ERROR;
|
|
319
|
-
}
|
|
234
|
+
function isAbortErrorOnWrite(error) {
|
|
235
|
+
return error.name === "AbortError" || error.message === "Invalid state: WritableStream is closed" || error.code === "ERR_HTTP2_INVALID_STREAM";
|
|
320
236
|
}
|
|
321
237
|
function restateLogLevelToWasmLogLevel(level) {
|
|
322
238
|
switch (level) {
|
|
@@ -329,6 +245,4 @@ function restateLogLevelToWasmLogLevel(level) {
|
|
|
329
245
|
}
|
|
330
246
|
|
|
331
247
|
//#endregion
|
|
332
|
-
exports.
|
|
333
|
-
exports.tryCreateContextualLogger = tryCreateContextualLogger;
|
|
334
|
-
exports.vm_log = vm_log;
|
|
248
|
+
exports.createRestateHandler = createRestateHandler;
|