@restatedev/restate-sdk 0.0.0-SNAPSHOT-20231025205407
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/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/connection/connection.d.ts +19 -0
- package/dist/connection/connection.d.ts.map +1 -0
- package/dist/connection/connection.js +13 -0
- package/dist/connection/connection.js.map +1 -0
- package/dist/connection/embedded_connection.d.ts +22 -0
- package/dist/connection/embedded_connection.d.ts.map +1 -0
- package/dist/connection/embedded_connection.js +78 -0
- package/dist/connection/embedded_connection.js.map +1 -0
- package/dist/connection/http_connection.d.ts +73 -0
- package/dist/connection/http_connection.d.ts.map +1 -0
- package/dist/connection/http_connection.js +203 -0
- package/dist/connection/http_connection.js.map +1 -0
- package/dist/connection/lambda_connection.d.ts +14 -0
- package/dist/connection/lambda_connection.d.ts.map +1 -0
- package/dist/connection/lambda_connection.js +56 -0
- package/dist/connection/lambda_connection.js.map +1 -0
- package/dist/embedded/api.d.ts +18 -0
- package/dist/embedded/api.d.ts.map +1 -0
- package/dist/embedded/api.js +37 -0
- package/dist/embedded/api.js.map +1 -0
- package/dist/embedded/handler.d.ts +4 -0
- package/dist/embedded/handler.d.ts.map +1 -0
- package/dist/embedded/handler.js +28 -0
- package/dist/embedded/handler.js.map +1 -0
- package/dist/embedded/http2_remote.d.ts +10 -0
- package/dist/embedded/http2_remote.d.ts.map +1 -0
- package/dist/embedded/http2_remote.js +85 -0
- package/dist/embedded/http2_remote.js.map +1 -0
- package/dist/embedded/invocation.d.ts +4 -0
- package/dist/embedded/invocation.d.ts.map +1 -0
- package/dist/embedded/invocation.js +90 -0
- package/dist/embedded/invocation.js.map +1 -0
- package/dist/generated/dev/restate/events.d.ts +96 -0
- package/dist/generated/dev/restate/events.d.ts.map +1 -0
- package/dist/generated/dev/restate/events.js +371 -0
- package/dist/generated/dev/restate/events.js.map +1 -0
- package/dist/generated/dev/restate/ext.d.ts +88 -0
- package/dist/generated/dev/restate/ext.d.ts.map +1 -0
- package/dist/generated/dev/restate/ext.js +212 -0
- package/dist/generated/dev/restate/ext.js.map +1 -0
- package/dist/generated/google/protobuf/descriptor.d.ts +1204 -0
- package/dist/generated/google/protobuf/descriptor.d.ts.map +1 -0
- package/dist/generated/google/protobuf/descriptor.js +6676 -0
- package/dist/generated/google/protobuf/descriptor.js.map +1 -0
- package/dist/generated/google/protobuf/empty.d.ts +86 -0
- package/dist/generated/google/protobuf/empty.d.ts.map +1 -0
- package/dist/generated/google/protobuf/empty.js +107 -0
- package/dist/generated/google/protobuf/empty.js.map +1 -0
- package/dist/generated/google/protobuf/struct.d.ts +175 -0
- package/dist/generated/google/protobuf/struct.d.ts.map +1 -0
- package/dist/generated/google/protobuf/struct.js +754 -0
- package/dist/generated/google/protobuf/struct.js.map +1 -0
- package/dist/generated/proto/discovery.d.ts +105 -0
- package/dist/generated/proto/discovery.d.ts.map +1 -0
- package/dist/generated/proto/discovery.js +364 -0
- package/dist/generated/proto/discovery.js.map +1 -0
- package/dist/generated/proto/dynrpc.d.ts +150 -0
- package/dist/generated/proto/dynrpc.d.ts.map +1 -0
- package/dist/generated/proto/dynrpc.js +668 -0
- package/dist/generated/proto/dynrpc.js.map +1 -0
- package/dist/generated/proto/javascript.d.ts +97 -0
- package/dist/generated/proto/javascript.d.ts.map +1 -0
- package/dist/generated/proto/javascript.js +297 -0
- package/dist/generated/proto/javascript.js.map +1 -0
- package/dist/generated/proto/protocol.d.ts +371 -0
- package/dist/generated/proto/protocol.d.ts.map +1 -0
- package/dist/generated/proto/protocol.js +2179 -0
- package/dist/generated/proto/protocol.js.map +1 -0
- package/dist/generated/proto/services.d.ts +307 -0
- package/dist/generated/proto/services.d.ts.map +1 -0
- package/dist/generated/proto/services.js +1535 -0
- package/dist/generated/proto/services.js.map +1 -0
- package/dist/generated/proto/test.d.ts +116 -0
- package/dist/generated/proto/test.d.ts.map +1 -0
- package/dist/generated/proto/test.js +321 -0
- package/dist/generated/proto/test.js.map +1 -0
- package/dist/invocation.d.ts +39 -0
- package/dist/invocation.d.ts.map +1 -0
- package/dist/invocation.js +138 -0
- package/dist/invocation.js.map +1 -0
- package/dist/io/decoder.d.ts +8 -0
- package/dist/io/decoder.d.ts.map +1 -0
- package/dist/io/decoder.js +133 -0
- package/dist/io/decoder.js.map +1 -0
- package/dist/io/encoder.d.ts +7 -0
- package/dist/io/encoder.d.ts.map +1 -0
- package/dist/io/encoder.js +57 -0
- package/dist/io/encoder.js.map +1 -0
- package/dist/journal.d.ts +42 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +368 -0
- package/dist/journal.js.map +1 -0
- package/dist/local_state_store.d.ts +13 -0
- package/dist/local_state_store.d.ts.map +1 -0
- package/dist/local_state_store.js +72 -0
- package/dist/local_state_store.js.map +1 -0
- package/dist/public_api.d.ts +10 -0
- package/dist/public_api.d.ts.map +1 -0
- package/dist/public_api.js +59 -0
- package/dist/public_api.js.map +1 -0
- package/dist/restate_context.d.ts +405 -0
- package/dist/restate_context.d.ts.map +1 -0
- package/dist/restate_context.js +46 -0
- package/dist/restate_context.js.map +1 -0
- package/dist/restate_context_impl.d.ts +54 -0
- package/dist/restate_context_impl.d.ts.map +1 -0
- package/dist/restate_context_impl.js +364 -0
- package/dist/restate_context_impl.js.map +1 -0
- package/dist/server/base_restate_server.d.ts +30 -0
- package/dist/server/base_restate_server.d.ts.map +1 -0
- package/dist/server/base_restate_server.js +360 -0
- package/dist/server/base_restate_server.js.map +1 -0
- package/dist/server/restate_lambda_handler.d.ts +104 -0
- package/dist/server/restate_lambda_handler.d.ts.map +1 -0
- package/dist/server/restate_lambda_handler.js +245 -0
- package/dist/server/restate_lambda_handler.js.map +1 -0
- package/dist/server/restate_server.d.ts +91 -0
- package/dist/server/restate_server.d.ts.map +1 -0
- package/dist/server/restate_server.js +230 -0
- package/dist/server/restate_server.js.map +1 -0
- package/dist/state_machine.d.ts +75 -0
- package/dist/state_machine.d.ts.map +1 -0
- package/dist/state_machine.js +380 -0
- package/dist/state_machine.js.map +1 -0
- package/dist/types/errors.d.ts +40 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +121 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/grpc.d.ts +88 -0
- package/dist/types/grpc.d.ts.map +1 -0
- package/dist/types/grpc.js +68 -0
- package/dist/types/grpc.js.map +1 -0
- package/dist/types/protocol.d.ts +24 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +115 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/router.d.ts +33 -0
- package/dist/types/router.d.ts.map +1 -0
- package/dist/types/router.js +36 -0
- package/dist/types/router.js.map +1 -0
- package/dist/types/types.d.ts +30 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +125 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/assumpsions.d.ts +8 -0
- package/dist/utils/assumpsions.d.ts.map +1 -0
- package/dist/utils/assumpsions.js +101 -0
- package/dist/utils/assumpsions.js.map +1 -0
- package/dist/utils/logger.d.ts +60 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +102 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/public_utils.d.ts +58 -0
- package/dist/utils/public_utils.d.ts.map +1 -0
- package/dist/utils/public_utils.js +49 -0
- package/dist/utils/public_utils.js.map +1 -0
- package/dist/utils/utils.d.ts +14 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +119 -0
- package/dist/utils/utils.js.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Restate Typescript SDK
|
|
2
|
+
|
|
3
|
+
[Restate](https://restate.dev/) is a system for easily building resilient applications using *distributed durable async/await*. This repository contains the Restate SDK for writing services in **Node.js / Typescript**.
|
|
4
|
+
|
|
5
|
+
Restate applications are composed of *durably executed, stateful RPC handlers* that can run either
|
|
6
|
+
as part of long-running processes, or as FaaS (AWS Lambda).
|
|
7
|
+
|
|
8
|
+
```typescript
|
|
9
|
+
// note that there is no failure handling in this example, because the combination of durable execution,
|
|
10
|
+
// communication, and state storage makes this unnecessary here.
|
|
11
|
+
const addToCart = async (ctx: restate.RpcContext, cartId: string /* the key */, ticketId: string) => {
|
|
12
|
+
// RPC participates in durable execution, so guaranteed to eventually happend and
|
|
13
|
+
// will never get duplicated. would suspend if the other takes too long
|
|
14
|
+
const success = await ctx.rpc<ticketApi>({ path: "tickets" }).reserve(ticketId);
|
|
15
|
+
|
|
16
|
+
if (success) {
|
|
17
|
+
const cart = (await ctx.get<string[]>("cart")) || []; // gets state 'cart' bound to current cartId
|
|
18
|
+
cart.push(ticketId);
|
|
19
|
+
ctx.set("cart", cart); // writes state bound to current cartId
|
|
20
|
+
|
|
21
|
+
// reliable delayed call sent from Restate, which also participaes in durable execution
|
|
22
|
+
ctx.sendDelayed<cartApi>({path: "cart"}, minutes(15)).expireTicket(ticketId);
|
|
23
|
+
}
|
|
24
|
+
return success;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
restate
|
|
30
|
+
.createServer()
|
|
31
|
+
.bindKeyedRouter("cart", restate.keyedRouter({ addToCart, expireTicket }))
|
|
32
|
+
.listen(9080);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Restate takes care of:
|
|
36
|
+
- **reliable execution:** handlers will always run to completion. Intermediate failures result in re-tries
|
|
37
|
+
that use the *durable execution* mechanism to recover partial progress and not duplicate already executed
|
|
38
|
+
steps.
|
|
39
|
+
- **suspending handlers:** long-running handlers suspend when awaiting on a promise (or when explicitly
|
|
40
|
+
sleeping) and resume when that promise is resolved. Lambdas finish, services may scale down.
|
|
41
|
+
- **reliable communication:** handlers communicate with *exactly-once semantics*. Restate reliably delivers
|
|
42
|
+
messages and anchors both sender and receiver in the durable execution to ensure no losses or duplicates
|
|
43
|
+
can happen.
|
|
44
|
+
- **durable timers:** handlers can sleep (and suspend) or schedule calls for later.
|
|
45
|
+
- **isolation:** handlers can be keyed, which makes Restate scheduled them to obey single-writer-per-key
|
|
46
|
+
semantics.
|
|
47
|
+
- **state:** keyed handlers can attach key/value state, which is eagerly pushed into handlers during
|
|
48
|
+
invocation, and written back upon completion. This is particularly efficient for FaaS deployments
|
|
49
|
+
(stateful serverless, yay!).
|
|
50
|
+
- **observability & introspection:** Restate automatically generates Open Telemetry traces for the
|
|
51
|
+
interactions between handlers and gives you a SQL shell to query the distributed state of the application.
|
|
52
|
+
- **gRPC support:** Handlers may optionally be defined as gRPC services, and Restate will act as the transport
|
|
53
|
+
layer for the services/clients in that case.
|
|
54
|
+
|
|
55
|
+
Check [Restate GitHub](https://github.com/restatedev/) or the [docs](https://docs.restate.dev/) for further details.
|
|
56
|
+
|
|
57
|
+
# Using the SDK
|
|
58
|
+
|
|
59
|
+
To use this SDK, simply add the dependency to your project:
|
|
60
|
+
```shell
|
|
61
|
+
npm install @restatedev/restate-sdk
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For brand-new projects, we recommend using the [Restate Node Template](https://github.com/restatedev/node-template-generator):
|
|
65
|
+
```shell
|
|
66
|
+
npx -y @restatedev/create-app
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
# Contributing to the SDK
|
|
70
|
+
|
|
71
|
+
### Prerequisites
|
|
72
|
+
- [NodeJS (and npm)](https://nodejs.org) installed
|
|
73
|
+
|
|
74
|
+
### Building the SDK
|
|
75
|
+
|
|
76
|
+
Install the dependencies, build the Restate protocol types (from ProtoBuf), and transpile the TypeScript code:
|
|
77
|
+
```shell
|
|
78
|
+
npm install
|
|
79
|
+
npm run proto
|
|
80
|
+
npm run build
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If everything goes well, the artifact would be created at `dist/`.
|
|
84
|
+
|
|
85
|
+
### Testing Changes
|
|
86
|
+
|
|
87
|
+
Run the tests via
|
|
88
|
+
```shell
|
|
89
|
+
npm run test
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Run the formatter and linter via
|
|
93
|
+
```shell
|
|
94
|
+
npm run format
|
|
95
|
+
npm run lint
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Launch a sample program (requires no build)
|
|
99
|
+
```shell
|
|
100
|
+
npm run example
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Testing end-to-end with Restate Runtime
|
|
104
|
+
|
|
105
|
+
This requires the [Docker Engine](https://docs.docker.com/engine/install/) to launch the Restate runtime for testing.
|
|
106
|
+
|
|
107
|
+
Start the runtime in a Docker container and tell Restate about the example service. This requires the example to be running, to make the discovery succeed!
|
|
108
|
+
- On Linux:
|
|
109
|
+
```shell
|
|
110
|
+
docker run --name restate_dev --rm --network=host ghcr.io/restatedev/restate-dist:latest
|
|
111
|
+
|
|
112
|
+
curl -X POST http://localhost:9070/endpoints -H 'content-type: application/json' -d '{"uri": "http://localhost:9080"}'
|
|
113
|
+
```
|
|
114
|
+
- On macOS:
|
|
115
|
+
```shell
|
|
116
|
+
docker run --name restate_dev --rm -p 9070:9070 -p 8080:8080 ghcr.io/restatedev/restate-dist:latest
|
|
117
|
+
|
|
118
|
+
curl -X POST http://localhost:9070/endpoints -H 'content-type: application/json' -d '{"uri": "http://host.docker.internal:9080"}'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
Invoke the example service from the command line:
|
|
123
|
+
```shell
|
|
124
|
+
curl -X POST http://localhost:8080/greeter/greet -H 'content-type: application/json' -d '{"name": "Pete"}'
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
# Releasing the package
|
|
128
|
+
|
|
129
|
+
## Releasing via release-it
|
|
130
|
+
|
|
131
|
+
Releasing a new npm package from this repo requires:
|
|
132
|
+
|
|
133
|
+
* [SSH access configured for Github](https://docs.github.com/en/authentication/connecting-to-github-with-ssh) in order to push commits and tags to GitHub
|
|
134
|
+
* A GitHub personal access token with access to https://github.com/restatedev/sdk-typescript in your environment as `GITHUB_TOKEN` in order to create a Github release
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npm run release
|
|
139
|
+
# now select what type of release you want to do and say yes to the rest of the options
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The actual `npm publish` is run by GitHub actions once a GitHub release is created.
|
|
143
|
+
|
|
144
|
+
## Releasing manually
|
|
145
|
+
|
|
146
|
+
1. Bump the version field in package.json to `X.Y.Z`
|
|
147
|
+
2. Create and push a tag of the form `vX.Y.Z` to the upstream repository
|
|
148
|
+
3. [Create a new GitHub release](https://github.com/restatedev/sdk-typescript/releases)
|
|
149
|
+
|
|
150
|
+
Creating the GitHub release will trigger `npm publish` via GitHub actions.
|
|
151
|
+
|
|
152
|
+
After having created a new SDK release, you need to:
|
|
153
|
+
|
|
154
|
+
1. [Update and release the tour of Restate](https://github.com/restatedev/tour-of-restate-typescript#upgrading-typescript-sdk)
|
|
155
|
+
2. [Update the Typescript SDK and Tour version in the documentation and release it](https://github.com/restatedev/documentation#upgrading-typescript-sdk-version)
|
|
156
|
+
3. [Update and release the Node template generator](https://github.com/restatedev/node-template-generator#upgrading-typescript-sdk)
|
|
157
|
+
4. [Update the examples](https://github.com/restatedev/examples#upgrading-the-sdk-dependency-for-restate-developers)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Message } from "../types/types";
|
|
2
|
+
/**
|
|
3
|
+
* A connection from the service/SDK to Restate.
|
|
4
|
+
* Accepts messages to be sent and committed to the journal.
|
|
5
|
+
*/
|
|
6
|
+
export interface Connection {
|
|
7
|
+
send(msg: Message): Promise<void>;
|
|
8
|
+
end(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A consumer of a message stream from Restate.
|
|
12
|
+
* Messages include journal replay messages and completion messages.
|
|
13
|
+
*/
|
|
14
|
+
export interface RestateStreamConsumer {
|
|
15
|
+
handleMessage(m: Message): boolean;
|
|
16
|
+
handleStreamError(e: Error): void;
|
|
17
|
+
handleInputClosed(): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAEnC,iBAAiB,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAElC,iBAAiB,IAAI,IAAI,CAAC;CAC3B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
|
|
4
|
+
*
|
|
5
|
+
* This file is part of the Restate SDK for Node.js/TypeScript,
|
|
6
|
+
* which is released under the MIT license.
|
|
7
|
+
*
|
|
8
|
+
* You can find a copy of the license in file LICENSE in the root
|
|
9
|
+
* directory of this repository or package, or at
|
|
10
|
+
* https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RemoteContext } from "../generated/proto/services";
|
|
2
|
+
import { Message } from "../types/types";
|
|
3
|
+
import { Connection } from "./connection";
|
|
4
|
+
export declare class FencedOffError extends Error {
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
export declare class InvocationAlreadyCompletedError extends Error {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
export declare class EmbeddedConnection implements Connection {
|
|
11
|
+
private readonly operationId;
|
|
12
|
+
private readonly streamId;
|
|
13
|
+
private readonly remote;
|
|
14
|
+
private queue;
|
|
15
|
+
private flushing;
|
|
16
|
+
constructor(operationId: string, streamId: string, remote: RemoteContext);
|
|
17
|
+
send(msg: Message): Promise<void>;
|
|
18
|
+
end(): Promise<void>;
|
|
19
|
+
private scheduleFlush;
|
|
20
|
+
private flush;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=embedded_connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded_connection.d.ts","sourceRoot":"","sources":["../../src/connection/embedded_connection.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,qBAAa,cAAe,SAAQ,KAAK;;CAIxC;AAED,qBAAa,+BAAgC,SAAQ,KAAK;;CAIzD;AAED,qBAAa,kBAAmB,YAAW,UAAU;IAKjD,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,QAAQ,CAAoC;gBAGjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa;IAGxC,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAKpB,OAAO,CAAC,aAAa;YASP,KAAK;CAoBpB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
|
|
4
|
+
*
|
|
5
|
+
* This file is part of the Restate SDK for Node.js/TypeScript,
|
|
6
|
+
* which is released under the MIT license.
|
|
7
|
+
*
|
|
8
|
+
* You can find a copy of the license in file LICENSE in the root
|
|
9
|
+
* directory of this repository or package, or at
|
|
10
|
+
* https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.EmbeddedConnection = exports.InvocationAlreadyCompletedError = exports.FencedOffError = void 0;
|
|
14
|
+
const encoder_1 = require("../io/encoder");
|
|
15
|
+
class FencedOffError extends Error {
|
|
16
|
+
constructor() {
|
|
17
|
+
super("FencedOff");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.FencedOffError = FencedOffError;
|
|
21
|
+
class InvocationAlreadyCompletedError extends Error {
|
|
22
|
+
constructor() {
|
|
23
|
+
super("Completed");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.InvocationAlreadyCompletedError = InvocationAlreadyCompletedError;
|
|
27
|
+
class EmbeddedConnection {
|
|
28
|
+
operationId;
|
|
29
|
+
streamId;
|
|
30
|
+
remote;
|
|
31
|
+
queue = [];
|
|
32
|
+
flushing = Promise.resolve();
|
|
33
|
+
constructor(operationId, streamId, remote) {
|
|
34
|
+
this.operationId = operationId;
|
|
35
|
+
this.streamId = streamId;
|
|
36
|
+
this.remote = remote;
|
|
37
|
+
}
|
|
38
|
+
send(msg) {
|
|
39
|
+
const len = this.queue.push(msg);
|
|
40
|
+
if (len === 1) {
|
|
41
|
+
// we are the first in line, therefore we schedule a flush,
|
|
42
|
+
// BUT we must wait for the previous flush to end.
|
|
43
|
+
this.flushing = this.flushing.then(() => this.scheduleFlush());
|
|
44
|
+
}
|
|
45
|
+
// tag along to the previously scheduled flush.
|
|
46
|
+
return this.flushing;
|
|
47
|
+
}
|
|
48
|
+
end() {
|
|
49
|
+
this.flushing = this.flushing.then(() => this.flush());
|
|
50
|
+
return this.flushing;
|
|
51
|
+
}
|
|
52
|
+
scheduleFlush() {
|
|
53
|
+
// schedule a flush at the end of the current event loop iteration.
|
|
54
|
+
return new Promise((resolve, reject) => setImmediate(() => {
|
|
55
|
+
this.flush().then(resolve).catch(reject);
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
async flush() {
|
|
59
|
+
if (this.queue.length === 0) {
|
|
60
|
+
return Promise.resolve();
|
|
61
|
+
}
|
|
62
|
+
const buffer = (0, encoder_1.encodeMessages)(this.queue);
|
|
63
|
+
this.queue = [];
|
|
64
|
+
const res = await this.remote.send({
|
|
65
|
+
operationId: this.operationId,
|
|
66
|
+
streamId: this.streamId,
|
|
67
|
+
messages: buffer,
|
|
68
|
+
});
|
|
69
|
+
if (res.invalidStream !== undefined) {
|
|
70
|
+
throw new FencedOffError();
|
|
71
|
+
}
|
|
72
|
+
if (res.invocationCompleted !== undefined) {
|
|
73
|
+
throw new InvocationAlreadyCompletedError();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.EmbeddedConnection = EmbeddedConnection;
|
|
78
|
+
//# sourceMappingURL=embedded_connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded_connection.js","sourceRoot":"","sources":["../../src/connection/embedded_connection.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAGH,2CAA+C;AAI/C,MAAa,cAAe,SAAQ,KAAK;IACvC;QACE,KAAK,CAAC,WAAW,CAAC,CAAC;IACrB,CAAC;CACF;AAJD,wCAIC;AAED,MAAa,+BAAgC,SAAQ,KAAK;IACxD;QACE,KAAK,CAAC,WAAW,CAAC,CAAC;IACrB,CAAC;CACF;AAJD,0EAIC;AAED,MAAa,kBAAkB;IAKV;IACA;IACA;IANX,KAAK,GAAc,EAAE,CAAC;IACtB,QAAQ,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEpD,YACmB,WAAmB,EACnB,QAAgB,EAChB,MAAqB;QAFrB,gBAAW,GAAX,WAAW,CAAQ;QACnB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAe;IACrC,CAAC;IAEJ,IAAI,CAAC,GAAY;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,GAAG,KAAK,CAAC,EAAE;YACb,2DAA2D;YAC3D,kDAAkD;YAClD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;SAChE;QACD,+CAA+C;QAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,GAAG;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,aAAa;QACnB,mEAAmE;QACnE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CACrC,YAAY,CAAC,GAAG,EAAE;YAChB,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;YAC3B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;SAC1B;QACD,MAAM,MAAM,GAAG,IAAA,wBAAc,EAAC,IAAI,CAAC,KAAK,CAAW,CAAC;QACpD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAEhB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACjC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;QAEH,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS,EAAE;YACnC,MAAM,IAAI,cAAc,EAAE,CAAC;SAC5B;QACD,IAAI,GAAG,CAAC,mBAAmB,KAAK,SAAS,EAAE;YACzC,MAAM,IAAI,+BAA+B,EAAE,CAAC;SAC7C;IACH,CAAC;CACF;AAvDD,gDAuDC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import stream from "stream";
|
|
3
|
+
import { Connection, RestateStreamConsumer } from "./connection";
|
|
4
|
+
import { Message } from "../types/types";
|
|
5
|
+
/**
|
|
6
|
+
* A duplex stream with Restate Messages over HTTP2.
|
|
7
|
+
*
|
|
8
|
+
* This stream handles the following concerns:
|
|
9
|
+
*
|
|
10
|
+
* (1) encoding and decoding of messages from and from raw bytes
|
|
11
|
+
*
|
|
12
|
+
* (2) buffering the outgoing messages, because the call sites that produce (potentially) large
|
|
13
|
+
* messages might not await their transfer. Aside from the fact that we achieve better pipelining
|
|
14
|
+
* that way, we also simply cannot guarantee that users of the Restate SDK actually await the
|
|
15
|
+
* relevant async API methods.
|
|
16
|
+
*
|
|
17
|
+
* This stream essentially buffers messages and, upon flush, sends them asynchronously, as the
|
|
18
|
+
* stream has availability. Flush requests queue up, if new data gets flushed while the previous
|
|
19
|
+
* data is still being sent.
|
|
20
|
+
*
|
|
21
|
+
* (3) Input messages can be pipelined to a sequence of consumers. For example, first to a journal,
|
|
22
|
+
* and afterwards to the state machine.
|
|
23
|
+
*
|
|
24
|
+
* (4) Handling the relevant stream events for errors and consolidating them to one error handler, plus
|
|
25
|
+
* notifications for cleanly closed input (to trigger suspension).
|
|
26
|
+
*/
|
|
27
|
+
export declare class RestateHttp2Connection implements Connection {
|
|
28
|
+
private readonly rawStream;
|
|
29
|
+
/**
|
|
30
|
+
* create a RestateDuplex stream from an http2 (duplex) stream.
|
|
31
|
+
*/
|
|
32
|
+
static from(http2stream: stream.Duplex): RestateHttp2Connection;
|
|
33
|
+
private readonly sdkInput;
|
|
34
|
+
private readonly sdkOutput;
|
|
35
|
+
private currentConsumer;
|
|
36
|
+
private inputBuffer;
|
|
37
|
+
private consumerError?;
|
|
38
|
+
private consumerInputClosed;
|
|
39
|
+
constructor(rawStream: stream.Duplex);
|
|
40
|
+
/**
|
|
41
|
+
* Pipes the messages from this connection to the given consumer. The consumer
|
|
42
|
+
* will also receive error and stream closing notifications.
|
|
43
|
+
*
|
|
44
|
+
* Once the 'handleMessage()' method returns 'true', the consumer is immediately removed.
|
|
45
|
+
* That way, consumers can consume a bounded amount of messages (like just the initial journal).
|
|
46
|
+
*
|
|
47
|
+
* There can only be one consumer at a time.
|
|
48
|
+
*/
|
|
49
|
+
pipeToConsumer(consumer: RestateStreamConsumer): void;
|
|
50
|
+
/**
|
|
51
|
+
* Removes the current consumer, if there is one.
|
|
52
|
+
*/
|
|
53
|
+
removeCurrentConsumer(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Adds a message to the output stream.
|
|
56
|
+
*
|
|
57
|
+
* This always puts the message into the node stream, but will return a promise that is resolved once
|
|
58
|
+
* further messages can be written.
|
|
59
|
+
*
|
|
60
|
+
* The reasoning is that some, but not all Restate operations return promises and are typically
|
|
61
|
+
* awaited. For example, rpc, sleep, side-effect have promises and are awaited, while one-way-sends and
|
|
62
|
+
* state updates don't return promises.
|
|
63
|
+
*
|
|
64
|
+
* As a pragmatic solution, we always accept messages, but return a promise for when the output has
|
|
65
|
+
* capacity again, so that at least the operations that await results will respect backpressure.
|
|
66
|
+
*/
|
|
67
|
+
send(msg: Message): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Ends the stream, awaiting pending writes.
|
|
70
|
+
*/
|
|
71
|
+
end(): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=http_connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http_connection.d.ts","sourceRoot":"","sources":["../../src/connection/http_connection.ts"],"names":[],"mappings":";AAWA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAOzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,sBAAuB,YAAW,UAAU;IAuB3C,OAAO,CAAC,QAAQ,CAAC,SAAS;IAtBtC;;OAEG;WACW,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,GAAG,sBAAsB;IAOtE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAI3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAG5C,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,aAAa,CAAC,CAAQ;IAC9B,OAAO,CAAC,mBAAmB,CAAS;gBAEP,SAAS,EAAE,MAAM,CAAC,MAAM;IAuErD;;;;;;;;OAQG;IACI,cAAc,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IA+B5D;;OAEG;IACI,qBAAqB,IAAI,IAAI;IAQpC;;;;;;;;;;;;OAYG;IACI,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxC;;OAEG;IACU,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAUlC"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
|
|
4
|
+
*
|
|
5
|
+
* This file is part of the Restate SDK for Node.js/TypeScript,
|
|
6
|
+
* which is released under the MIT license.
|
|
7
|
+
*
|
|
8
|
+
* You can find a copy of the license in file LICENSE in the root
|
|
9
|
+
* directory of this repository or package, or at
|
|
10
|
+
* https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RestateHttp2Connection = void 0;
|
|
14
|
+
const encoder_1 = require("../io/encoder");
|
|
15
|
+
const decoder_1 = require("../io/decoder");
|
|
16
|
+
const logger_1 = require("../utils/logger");
|
|
17
|
+
const promises_1 = require("stream/promises");
|
|
18
|
+
// utility promise, for cases where we want to save allocation of an extra promise
|
|
19
|
+
const RESOLVED = Promise.resolve();
|
|
20
|
+
/**
|
|
21
|
+
* A duplex stream with Restate Messages over HTTP2.
|
|
22
|
+
*
|
|
23
|
+
* This stream handles the following concerns:
|
|
24
|
+
*
|
|
25
|
+
* (1) encoding and decoding of messages from and from raw bytes
|
|
26
|
+
*
|
|
27
|
+
* (2) buffering the outgoing messages, because the call sites that produce (potentially) large
|
|
28
|
+
* messages might not await their transfer. Aside from the fact that we achieve better pipelining
|
|
29
|
+
* that way, we also simply cannot guarantee that users of the Restate SDK actually await the
|
|
30
|
+
* relevant async API methods.
|
|
31
|
+
*
|
|
32
|
+
* This stream essentially buffers messages and, upon flush, sends them asynchronously, as the
|
|
33
|
+
* stream has availability. Flush requests queue up, if new data gets flushed while the previous
|
|
34
|
+
* data is still being sent.
|
|
35
|
+
*
|
|
36
|
+
* (3) Input messages can be pipelined to a sequence of consumers. For example, first to a journal,
|
|
37
|
+
* and afterwards to the state machine.
|
|
38
|
+
*
|
|
39
|
+
* (4) Handling the relevant stream events for errors and consolidating them to one error handler, plus
|
|
40
|
+
* notifications for cleanly closed input (to trigger suspension).
|
|
41
|
+
*/
|
|
42
|
+
class RestateHttp2Connection {
|
|
43
|
+
rawStream;
|
|
44
|
+
/**
|
|
45
|
+
* create a RestateDuplex stream from an http2 (duplex) stream.
|
|
46
|
+
*/
|
|
47
|
+
static from(http2stream) {
|
|
48
|
+
return new RestateHttp2Connection(http2stream);
|
|
49
|
+
}
|
|
50
|
+
// --------------------------------------------------------------------------
|
|
51
|
+
// input as decoded messages
|
|
52
|
+
sdkInput;
|
|
53
|
+
// output as encoded bytes. we convert manually, not as transforms,
|
|
54
|
+
// to skip a layer of stream indirection
|
|
55
|
+
sdkOutput;
|
|
56
|
+
// consumer handling
|
|
57
|
+
currentConsumer = null;
|
|
58
|
+
inputBuffer = [];
|
|
59
|
+
consumerError;
|
|
60
|
+
consumerInputClosed = false;
|
|
61
|
+
constructor(rawStream) {
|
|
62
|
+
this.rawStream = rawStream;
|
|
63
|
+
this.sdkInput = rawStream.pipe((0, decoder_1.streamDecoder)());
|
|
64
|
+
this.sdkOutput = rawStream;
|
|
65
|
+
// remember and forward messages
|
|
66
|
+
this.sdkInput.on("data", (m) => {
|
|
67
|
+
// deliver message, if we have a consumer. otherwise buffer the message.
|
|
68
|
+
if (this.currentConsumer) {
|
|
69
|
+
if (this.currentConsumer.handleMessage(m)) {
|
|
70
|
+
this.removeCurrentConsumer();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.inputBuffer.push(m);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// remember and forward close events
|
|
78
|
+
this.sdkInput.on("end", () => {
|
|
79
|
+
this.consumerInputClosed = true;
|
|
80
|
+
if (this.currentConsumer) {
|
|
81
|
+
this.currentConsumer.handleInputClosed();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// --------- error handling --------
|
|
85
|
+
// - a.k.a. node event wrangling...
|
|
86
|
+
// the error handler for all sorts of errors coming from streams
|
|
87
|
+
const errorHandler = (e) => {
|
|
88
|
+
// make sure we don't overwrite the initial error
|
|
89
|
+
if (this.consumerError !== undefined) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.consumerError = e;
|
|
93
|
+
if (this.currentConsumer) {
|
|
94
|
+
this.currentConsumer.handleStreamError(e);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
// those two event types should cover all types of connection losses
|
|
98
|
+
rawStream.on("aborted", () => {
|
|
99
|
+
logger_1.rlog.error("Connection to Restate was lost");
|
|
100
|
+
errorHandler(new Error("Connection to Restate was lost"));
|
|
101
|
+
});
|
|
102
|
+
// this is both the raw http2 stream and the output SDK->Restate
|
|
103
|
+
rawStream.on("error", (e) => {
|
|
104
|
+
logger_1.rlog.error("Error in http2 stream to Restate: " + (e.stack ?? e.message));
|
|
105
|
+
errorHandler(e);
|
|
106
|
+
});
|
|
107
|
+
// these events notify of errors in the decoding pipeline
|
|
108
|
+
this.sdkInput.on("error", (e) => {
|
|
109
|
+
logger_1.rlog.error("Error in input stream (Restate to Service): " + (e.stack ?? e.message));
|
|
110
|
+
errorHandler(e);
|
|
111
|
+
});
|
|
112
|
+
// see if streams get torn down before they end cleanly
|
|
113
|
+
this.sdkInput.on("close", () => {
|
|
114
|
+
if (!this.consumerInputClosed) {
|
|
115
|
+
errorHandler(new Error("stream was destroyed before end"));
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// --------------------------------------------------------------------------
|
|
120
|
+
// input stream handling
|
|
121
|
+
// --------------------------------------------------------------------------
|
|
122
|
+
/**
|
|
123
|
+
* Pipes the messages from this connection to the given consumer. The consumer
|
|
124
|
+
* will also receive error and stream closing notifications.
|
|
125
|
+
*
|
|
126
|
+
* Once the 'handleMessage()' method returns 'true', the consumer is immediately removed.
|
|
127
|
+
* That way, consumers can consume a bounded amount of messages (like just the initial journal).
|
|
128
|
+
*
|
|
129
|
+
* There can only be one consumer at a time.
|
|
130
|
+
*/
|
|
131
|
+
pipeToConsumer(consumer) {
|
|
132
|
+
if (this.currentConsumer !== null) {
|
|
133
|
+
throw new Error("Already piping to a consumer");
|
|
134
|
+
}
|
|
135
|
+
this.currentConsumer = consumer;
|
|
136
|
+
// propagate pre-existing information
|
|
137
|
+
if (this.consumerError) {
|
|
138
|
+
consumer.handleStreamError(this.consumerError);
|
|
139
|
+
}
|
|
140
|
+
if (this.consumerInputClosed) {
|
|
141
|
+
consumer.handleInputClosed();
|
|
142
|
+
}
|
|
143
|
+
// pipe the buffered input messages, if we buffered some before the consumer was registered
|
|
144
|
+
const input = this.inputBuffer;
|
|
145
|
+
if (input.length > 0) {
|
|
146
|
+
let i = 0;
|
|
147
|
+
while (i < input.length) {
|
|
148
|
+
const done = consumer.handleMessage(input[i]);
|
|
149
|
+
i++;
|
|
150
|
+
if (done) {
|
|
151
|
+
this.removeCurrentConsumer();
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
this.inputBuffer = i === input.length ? [] : this.inputBuffer.slice(i);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Removes the current consumer, if there is one.
|
|
160
|
+
*/
|
|
161
|
+
removeCurrentConsumer() {
|
|
162
|
+
this.currentConsumer = null;
|
|
163
|
+
}
|
|
164
|
+
// --------------------------------------------------------------------------
|
|
165
|
+
// output stream handling
|
|
166
|
+
// --------------------------------------------------------------------------
|
|
167
|
+
/**
|
|
168
|
+
* Adds a message to the output stream.
|
|
169
|
+
*
|
|
170
|
+
* This always puts the message into the node stream, but will return a promise that is resolved once
|
|
171
|
+
* further messages can be written.
|
|
172
|
+
*
|
|
173
|
+
* The reasoning is that some, but not all Restate operations return promises and are typically
|
|
174
|
+
* awaited. For example, rpc, sleep, side-effect have promises and are awaited, while one-way-sends and
|
|
175
|
+
* state updates don't return promises.
|
|
176
|
+
*
|
|
177
|
+
* As a pragmatic solution, we always accept messages, but return a promise for when the output has
|
|
178
|
+
* capacity again, so that at least the operations that await results will respect backpressure.
|
|
179
|
+
*/
|
|
180
|
+
send(msg) {
|
|
181
|
+
const encodedMessage = (0, encoder_1.encodeMessage)(msg);
|
|
182
|
+
const hasMoreCapacity = this.sdkOutput.write(encodedMessage);
|
|
183
|
+
if (hasMoreCapacity) {
|
|
184
|
+
return RESOLVED;
|
|
185
|
+
}
|
|
186
|
+
return new Promise((resolve) => {
|
|
187
|
+
this.sdkOutput.once("drain", resolve);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Ends the stream, awaiting pending writes.
|
|
192
|
+
*/
|
|
193
|
+
async end() {
|
|
194
|
+
this.sdkOutput.end();
|
|
195
|
+
const options = {
|
|
196
|
+
error: true,
|
|
197
|
+
cleanup: true,
|
|
198
|
+
};
|
|
199
|
+
await (0, promises_1.finished)(this.rawStream, options);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.RestateHttp2Connection = RestateHttp2Connection;
|
|
203
|
+
//# sourceMappingURL=http_connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http_connection.js","sourceRoot":"","sources":["../../src/connection/http_connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Connection } from "./connection";
|
|
3
|
+
import { Message } from "../types/types";
|
|
4
|
+
export declare class LambdaConnection implements Connection {
|
|
5
|
+
private outputBuffer;
|
|
6
|
+
private suspendedOrCompleted;
|
|
7
|
+
private readonly completionPromise;
|
|
8
|
+
private resolveOnCompleted;
|
|
9
|
+
constructor();
|
|
10
|
+
send(msg: Message): Promise<void>;
|
|
11
|
+
getResult(): Promise<Buffer>;
|
|
12
|
+
end(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=lambda_connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lambda_connection.d.ts","sourceRoot":"","sources":["../../src/connection/lambda_connection.ts"],"names":[],"mappings":";AAWA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM1C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAKzC,qBAAa,gBAAiB,YAAW,UAAU;IAEjD,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,oBAAoB,CAAS;IAGrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkB;IACpD,OAAO,CAAC,kBAAkB,CAAiD;;IAU3E,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBjC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAI5B,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAQrB"}
|