@webda/grpc 4.0.0-beta.6 → 4.0.0-beta.7
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/.webda/cache +4 -4
- package/CHANGELOG.md +23 -0
- package/README.md +24 -10
- package/lib/grpc-context.d.ts +55 -0
- package/lib/grpc-context.d.ts.map +1 -0
- package/lib/grpc-context.js +83 -0
- package/lib/grpc-context.js.map +1 -0
- package/lib/grpc-stream.d.ts +13 -4
- package/lib/grpc-stream.d.ts.map +1 -1
- package/lib/grpc-stream.js +67 -23
- package/lib/grpc-stream.js.map +1 -1
- package/lib/grpcservice.service.d.ts +41 -23
- package/lib/grpcservice.service.d.ts.map +1 -1
- package/lib/grpcservice.service.js +155 -169
- package/lib/grpcservice.service.js.map +1 -1
- package/lib/proto-generator.js +1 -1
- package/lib/proto-generator.js.map +1 -1
- package/package.json +8 -5
- package/src/connect.e2e.spec.ts +114 -0
- package/src/grpc-context.ts +93 -0
- package/src/grpc-live.spec.ts +377 -0
- package/src/grpc-stream.spec.ts +122 -1
- package/src/grpc-stream.ts +63 -25
- package/src/grpcservice.service.ts +165 -196
- package/src/grpcservice.spec.ts +29 -442
- package/src/proto-generator.spec.ts +17 -0
- package/src/proto-generator.ts +1 -1
- package/src/query-statements.spec.ts +39 -13
- package/test/fixture.ts +166 -0
- package/webda.module.json +10 -0
package/test/fixture.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Service,
|
|
3
|
+
ServiceParameters,
|
|
4
|
+
WebContext,
|
|
5
|
+
WebdaError,
|
|
6
|
+
registerOperation,
|
|
7
|
+
registerSchema,
|
|
8
|
+
useApplication,
|
|
9
|
+
useContext
|
|
10
|
+
} from "@webda/core";
|
|
11
|
+
|
|
12
|
+
/** Observations of the fixture's generators. */
|
|
13
|
+
export const fixtureState = {
|
|
14
|
+
connectClosed: false,
|
|
15
|
+
ticksClosed: false,
|
|
16
|
+
floodClosed: false,
|
|
17
|
+
echoCalls: 0,
|
|
18
|
+
release: undefined as undefined | (() => void),
|
|
19
|
+
/** Lets Fixture.Ticks yield past its first tick */
|
|
20
|
+
open() {
|
|
21
|
+
this.release?.();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** Header of the current call, through the operation context */
|
|
26
|
+
const authorization = () => useContext<WebContext>().getHttpContext()?.getUniqueHeader("authorization") ?? "none";
|
|
27
|
+
|
|
28
|
+
/** Streaming operations for the transport tests. */
|
|
29
|
+
export class GrpcFixtureService extends Service {
|
|
30
|
+
/**
|
|
31
|
+
* @param params - raw parameters
|
|
32
|
+
* @returns parameters
|
|
33
|
+
*/
|
|
34
|
+
loadParameters(params: any): ServiceParameters {
|
|
35
|
+
return new ServiceParameters().load(params);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param text - text to echo
|
|
40
|
+
* @returns the text
|
|
41
|
+
*/
|
|
42
|
+
echo(text: string) {
|
|
43
|
+
fixtureState.echoCalls++;
|
|
44
|
+
if (text === "boom") throw new WebdaError.NotFound("Nothing to echo");
|
|
45
|
+
return { text, authorization: authorization() };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* An operation failing with an internal error whose message must not leave the server
|
|
50
|
+
* @param _text - unused
|
|
51
|
+
* @returns never
|
|
52
|
+
*/
|
|
53
|
+
leak(_text: string): { text: string } {
|
|
54
|
+
throw new Error("secret database password");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Bidirectional operation that never reads its input and keeps producing until it is cancelled
|
|
59
|
+
* @param _frames - incoming frames, ignored
|
|
60
|
+
* @returns outgoing frames
|
|
61
|
+
*/
|
|
62
|
+
async *flood(_frames: AsyncIterable<{ frame: string }>) {
|
|
63
|
+
try {
|
|
64
|
+
for (;;) {
|
|
65
|
+
yield { frame: "tick" };
|
|
66
|
+
await new Promise(resolve => setTimeout(resolve, 20));
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
fixtureState.floodClosed = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* An operation that raises a cancellation itself, the client being still there
|
|
75
|
+
* @param _text - unused
|
|
76
|
+
* @returns never
|
|
77
|
+
*/
|
|
78
|
+
abort(_text: string): { text: string } {
|
|
79
|
+
throw new WebdaError.OperationCancelledError();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Server stream gated after the first tick
|
|
84
|
+
* @param n - ticks
|
|
85
|
+
* @returns the ticks
|
|
86
|
+
*/
|
|
87
|
+
async *ticks(n: number) {
|
|
88
|
+
try {
|
|
89
|
+
yield { index: 1 };
|
|
90
|
+
await new Promise<void>(resolve => (fixtureState.release = resolve));
|
|
91
|
+
for (let index = 2; index <= n; index++) yield { index };
|
|
92
|
+
} finally {
|
|
93
|
+
fixtureState.ticksClosed = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Client stream
|
|
99
|
+
* @param values - the values
|
|
100
|
+
* @returns their sum
|
|
101
|
+
*/
|
|
102
|
+
async sum(values: AsyncIterable<{ value: number }>) {
|
|
103
|
+
let total = 0;
|
|
104
|
+
for await (const v of values) total += v.value;
|
|
105
|
+
return { total };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Bidirectional: greets with the caller's authorization header, then echoes every frame
|
|
110
|
+
* @param frames - incoming frames
|
|
111
|
+
* @returns outgoing frames
|
|
112
|
+
*/
|
|
113
|
+
async *connect(frames: AsyncIterable<{ frame: string }>) {
|
|
114
|
+
try {
|
|
115
|
+
yield { frame: `hello ${authorization()}` };
|
|
116
|
+
for await (const f of frames) {
|
|
117
|
+
if (f.frame === "fail") throw new WebdaError.NotFound("No such frame");
|
|
118
|
+
if (f.frame === "bye") return;
|
|
119
|
+
yield { frame: `echo ${f.frame} ${authorization()}` };
|
|
120
|
+
}
|
|
121
|
+
} finally {
|
|
122
|
+
fixtureState.connectClosed = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const schema = (name: string, value: any) => {
|
|
128
|
+
useApplication().getSchemas()[name] = value;
|
|
129
|
+
try {
|
|
130
|
+
registerSchema(name, value);
|
|
131
|
+
} catch {
|
|
132
|
+
// registered by a previous test
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/** Registers the fixture's schemas and operations (call once the app is up). */
|
|
137
|
+
export function registerGrpcFixture(): void {
|
|
138
|
+
const envelope = { type: "object", properties: { frame: { type: "string" } }, required: ["frame"] };
|
|
139
|
+
schema("Fixture.Echo.input", { type: "object", properties: { text: { type: "string" } }, required: ["text"] });
|
|
140
|
+
schema("Fixture.Echo.output", {
|
|
141
|
+
type: "object",
|
|
142
|
+
properties: { text: { type: "string" }, authorization: { type: "string" } }
|
|
143
|
+
});
|
|
144
|
+
schema("Fixture.Ticks.input", { type: "object", properties: { n: { type: "number" } }, required: ["n"] });
|
|
145
|
+
schema("Fixture.Tick", { type: "object", properties: { index: { type: "number" } }, "x-webda-stream": true });
|
|
146
|
+
schema("Fixture.Value", {
|
|
147
|
+
type: "object",
|
|
148
|
+
properties: { value: { type: "number" } },
|
|
149
|
+
required: ["value"],
|
|
150
|
+
"x-webda-stream": true
|
|
151
|
+
});
|
|
152
|
+
schema("Fixture.Total", { type: "object", properties: { total: { type: "number" } } });
|
|
153
|
+
schema("Fixture.Frame", { ...envelope, "x-webda-stream": true });
|
|
154
|
+
schema("Fixture.FrameOut", { ...envelope, "x-webda-stream": true });
|
|
155
|
+
const op = (id: string, method: string, extra: any) =>
|
|
156
|
+
registerOperation(id, { service: "Fixture", method, ...extra });
|
|
157
|
+
op("Fixture.Echo", "echo", { input: "Fixture.Echo.input", output: "Fixture.Echo.output" });
|
|
158
|
+
op("Fixture.Leak", "leak", { input: "Fixture.Echo.input", output: "Fixture.Echo.output" });
|
|
159
|
+
op("Fixture.Flood", "flood", { input: "Fixture.Frame", output: "Fixture.FrameOut" });
|
|
160
|
+
op("Fixture.Abort", "abort", { input: "Fixture.Echo.input", output: "Fixture.Echo.output" });
|
|
161
|
+
op("Fixture.Ticks", "ticks", { input: "Fixture.Ticks.input", output: "Fixture.Tick" });
|
|
162
|
+
op("Fixture.Sum", "sum", { input: "Fixture.Value", output: "Fixture.Total" });
|
|
163
|
+
op("Fixture.Connect", "connect", { input: "Fixture.Frame", output: "Fixture.FrameOut" });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const GRPC_FIXTURE_SERVICES = { Fixture: { type: "Webda/GrpcFixtureService" } };
|
package/webda.module.json
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
"additionalProperties": false,
|
|
11
11
|
"description": "Parameters for the gRPC service",
|
|
12
12
|
"properties": {
|
|
13
|
+
"maxQueuedBytes": {
|
|
14
|
+
"default": 16777216,
|
|
15
|
+
"description": "Most bytes of unconsumed messages a client or bidirectional operation may have queued; above it the call fails\nwith RESOURCE_EXHAUSTED",
|
|
16
|
+
"type": "number"
|
|
17
|
+
},
|
|
18
|
+
"maxQueuedMessages": {
|
|
19
|
+
"default": 1000,
|
|
20
|
+
"description": "Most unconsumed messages a client or bidirectional operation may have queued; above it the call fails with\nRESOURCE_EXHAUSTED",
|
|
21
|
+
"type": "number"
|
|
22
|
+
},
|
|
13
23
|
"operations": {
|
|
14
24
|
"default": [
|
|
15
25
|
"*"
|