@milaboratories/pl-client 2.16.26 → 2.16.28
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/README.md +2 -1
- package/dist/core/PromiseTracker.cjs +1 -3
- package/dist/core/PromiseTracker.cjs.map +1 -1
- package/dist/core/PromiseTracker.d.ts.map +1 -1
- package/dist/core/PromiseTracker.js +1 -3
- package/dist/core/PromiseTracker.js.map +1 -1
- package/dist/core/StatefulPromise.cjs +4 -4
- package/dist/core/StatefulPromise.cjs.map +1 -1
- package/dist/core/StatefulPromise.d.ts +1 -1
- package/dist/core/StatefulPromise.d.ts.map +1 -1
- package/dist/core/StatefulPromise.js +4 -4
- package/dist/core/StatefulPromise.js.map +1 -1
- package/dist/core/advisory_locks.cjs +1 -1
- package/dist/core/advisory_locks.cjs.map +1 -1
- package/dist/core/advisory_locks.js +1 -1
- package/dist/core/advisory_locks.js.map +1 -1
- package/dist/core/auth.cjs.map +1 -1
- package/dist/core/auth.d.ts +1 -1
- package/dist/core/auth.js.map +1 -1
- package/dist/core/cache.d.ts +1 -1
- package/dist/core/client.cjs +14 -14
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +11 -11
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +14 -14
- package/dist/core/client.js.map +1 -1
- package/dist/core/config.cjs +39 -39
- package/dist/core/config.cjs.map +1 -1
- package/dist/core/config.d.ts +5 -5
- package/dist/core/config.js +39 -39
- package/dist/core/config.js.map +1 -1
- package/dist/core/default_client.cjs +23 -23
- package/dist/core/default_client.cjs.map +1 -1
- package/dist/core/default_client.d.ts +3 -3
- package/dist/core/default_client.js +23 -23
- package/dist/core/default_client.js.map +1 -1
- package/dist/core/driver.cjs +1 -1
- package/dist/core/driver.cjs.map +1 -1
- package/dist/core/driver.d.ts +5 -5
- package/dist/core/driver.js +1 -1
- package/dist/core/driver.js.map +1 -1
- package/dist/core/error_resource.cjs +2 -2
- package/dist/core/error_resource.cjs.map +1 -1
- package/dist/core/error_resource.d.ts +1 -1
- package/dist/core/error_resource.js +2 -2
- package/dist/core/error_resource.js.map +1 -1
- package/dist/core/errors.cjs +24 -24
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +24 -24
- package/dist/core/errors.js.map +1 -1
- package/dist/core/final.cjs +43 -43
- package/dist/core/final.cjs.map +1 -1
- package/dist/core/final.d.ts +3 -3
- package/dist/core/final.d.ts.map +1 -1
- package/dist/core/final.js +43 -43
- package/dist/core/final.js.map +1 -1
- package/dist/core/ll_client.cjs +50 -43
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +9 -9
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +50 -43
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/ll_transaction.cjs +9 -9
- package/dist/core/ll_transaction.cjs.map +1 -1
- package/dist/core/ll_transaction.d.ts +7 -7
- package/dist/core/ll_transaction.d.ts.map +1 -1
- package/dist/core/ll_transaction.js +9 -9
- package/dist/core/ll_transaction.js.map +1 -1
- package/dist/core/stat.cjs.map +1 -1
- package/dist/core/stat.d.ts +1 -1
- package/dist/core/stat.js.map +1 -1
- package/dist/core/transaction.cjs +46 -46
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts +7 -7
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +46 -46
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/type_conversion.cjs +22 -22
- package/dist/core/type_conversion.cjs.map +1 -1
- package/dist/core/type_conversion.d.ts +3 -3
- package/dist/core/type_conversion.d.ts.map +1 -1
- package/dist/core/type_conversion.js +22 -22
- package/dist/core/type_conversion.js.map +1 -1
- package/dist/core/types.cjs +25 -25
- package/dist/core/types.cjs.map +1 -1
- package/dist/core/types.d.ts +7 -7
- package/dist/core/types.js +25 -25
- package/dist/core/types.js.map +1 -1
- package/dist/core/unauth_client.cjs +6 -4
- package/dist/core/unauth_client.cjs.map +1 -1
- package/dist/core/unauth_client.d.ts +4 -4
- package/dist/core/unauth_client.d.ts.map +1 -1
- package/dist/core/unauth_client.js +6 -4
- package/dist/core/unauth_client.js.map +1 -1
- package/dist/core/websocket_stream.cjs +22 -20
- package/dist/core/websocket_stream.cjs.map +1 -1
- package/dist/core/websocket_stream.d.ts +3 -3
- package/dist/core/websocket_stream.d.ts.map +1 -1
- package/dist/core/websocket_stream.js +22 -20
- package/dist/core/websocket_stream.js.map +1 -1
- package/dist/core/wire.d.ts +6 -6
- package/dist/core/wire.d.ts.map +1 -1
- package/dist/helpers/pl.cjs +19 -19
- package/dist/helpers/pl.cjs.map +1 -1
- package/dist/helpers/pl.d.ts +2 -2
- package/dist/helpers/pl.js +19 -19
- package/dist/helpers/pl.js.map +1 -1
- package/dist/helpers/poll.cjs +6 -6
- package/dist/helpers/poll.cjs.map +1 -1
- package/dist/helpers/poll.d.ts +4 -4
- package/dist/helpers/poll.d.ts.map +1 -1
- package/dist/helpers/poll.js +6 -6
- package/dist/helpers/poll.js.map +1 -1
- package/dist/helpers/retry_strategy.cjs +1 -1
- package/dist/helpers/retry_strategy.cjs.map +1 -1
- package/dist/helpers/retry_strategy.d.ts.map +1 -1
- package/dist/helpers/retry_strategy.js +1 -1
- package/dist/helpers/retry_strategy.js.map +1 -1
- package/dist/helpers/state_helpers.d.ts +2 -2
- package/dist/helpers/tx_helpers.cjs +2 -2
- package/dist/helpers/tx_helpers.cjs.map +1 -1
- package/dist/helpers/tx_helpers.d.ts +2 -2
- package/dist/helpers/tx_helpers.d.ts.map +1 -1
- package/dist/helpers/tx_helpers.js +2 -2
- package/dist/helpers/tx_helpers.js.map +1 -1
- package/dist/index.d.ts +16 -16
- package/dist/proto-grpc/google/protobuf/struct.d.ts +1 -1
- package/dist/proto-grpc/google/protobuf/struct.d.ts.map +1 -1
- package/dist/proto-rest/index.cjs +4 -5
- package/dist/proto-rest/index.cjs.map +1 -1
- package/dist/proto-rest/index.d.ts +4 -4
- package/dist/proto-rest/index.d.ts.map +1 -1
- package/dist/proto-rest/index.js +4 -5
- package/dist/proto-rest/index.js.map +1 -1
- package/dist/proto-rest/plapi.d.ts.map +1 -1
- package/dist/test/tcp-proxy.cjs +11 -10
- package/dist/test/tcp-proxy.cjs.map +1 -1
- package/dist/test/tcp-proxy.d.ts +1 -1
- package/dist/test/tcp-proxy.d.ts.map +1 -1
- package/dist/test/tcp-proxy.js +11 -10
- package/dist/test/tcp-proxy.js.map +1 -1
- package/dist/test/test_config.cjs +21 -17
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts +6 -6
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +21 -17
- package/dist/test/test_config.js.map +1 -1
- package/dist/util/pl.cjs +1 -1
- package/dist/util/pl.cjs.map +1 -1
- package/dist/util/pl.js +1 -1
- package/dist/util/pl.js.map +1 -1
- package/dist/util/util.cjs +1 -1
- package/dist/util/util.cjs.map +1 -1
- package/dist/util/util.js +1 -1
- package/dist/util/util.js.map +1 -1
- package/package.json +23 -23
- package/src/core/PromiseTracker.ts +3 -4
- package/src/core/StatefulPromise.ts +17 -8
- package/src/core/abstract_stream.ts +3 -4
- package/src/core/advisory_locks.ts +1 -1
- package/src/core/auth.ts +2 -2
- package/src/core/cache.ts +1 -1
- package/src/core/client.test.ts +25 -21
- package/src/core/client.ts +54 -45
- package/src/core/config.test.ts +44 -44
- package/src/core/config.ts +49 -49
- package/src/core/connectivity.test.ts +69 -63
- package/src/core/default_client.ts +46 -46
- package/src/core/driver.ts +6 -6
- package/src/core/error.test.ts +5 -5
- package/src/core/error_resource.ts +3 -3
- package/src/core/errors.ts +39 -31
- package/src/core/final.ts +48 -55
- package/src/core/ll_client.test.ts +53 -36
- package/src/core/ll_client.ts +125 -81
- package/src/core/ll_transaction.test.ts +75 -49
- package/src/core/ll_transaction.ts +37 -35
- package/src/core/stat.ts +1 -1
- package/src/core/transaction.test.ts +65 -65
- package/src/core/transaction.ts +91 -84
- package/src/core/type_conversion.ts +30 -31
- package/src/core/types.test.ts +6 -6
- package/src/core/types.ts +35 -35
- package/src/core/unauth_client.test.ts +18 -14
- package/src/core/unauth_client.ts +14 -12
- package/src/core/websocket_stream.test.ts +52 -52
- package/src/core/websocket_stream.ts +41 -37
- package/src/core/wire.ts +10 -8
- package/src/helpers/pl.ts +22 -22
- package/src/helpers/poll.ts +13 -27
- package/src/helpers/retry_strategy.ts +2 -4
- package/src/helpers/rich_resource_types.test.ts +2 -2
- package/src/helpers/state_helpers.ts +3 -3
- package/src/helpers/tx_helpers.ts +9 -7
- package/src/index.ts +16 -16
- package/src/proto-grpc/google/protobuf/struct.ts +1 -1
- package/src/proto-rest/index.ts +17 -18
- package/src/proto-rest/plapi.ts +1472 -1472
- package/src/test/tcp-proxy.ts +55 -54
- package/src/test/test_config.test.ts +3 -3
- package/src/test/test_config.ts +51 -46
- package/src/util/pl.ts +1 -1
- package/src/util/util.test.ts +5 -5
- package/src/util/util.ts +1 -1
- package/dist/helpers/rich_resource_types.d.ts +0 -2
- package/dist/helpers/rich_resource_types.d.ts.map +0 -1
- package/dist/helpers/smart_accessors.d.ts +0 -2
- package/dist/helpers/smart_accessors.d.ts.map +0 -1
- package/src/helpers/rich_resource_types.ts +0 -84
- package/src/helpers/smart_accessors.ts +0 -146
|
@@ -1,57 +1,75 @@
|
|
|
1
|
-
import { getTestLLClient } from
|
|
2
|
-
import { TxAPI_Open_Request_WritableTx } from
|
|
3
|
-
import { createLocalResourceId } from
|
|
4
|
-
import { test, expect } from
|
|
1
|
+
import { getTestLLClient } from "../test/test_config";
|
|
2
|
+
import { TxAPI_Open_Request_WritableTx } from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api";
|
|
3
|
+
import { createLocalResourceId } from "./types";
|
|
4
|
+
import { test, expect } from "vitest";
|
|
5
5
|
|
|
6
|
-
import { isTimeoutOrCancelError } from
|
|
7
|
-
import { Aborted } from
|
|
6
|
+
import { isTimeoutOrCancelError } from "./errors";
|
|
7
|
+
import { Aborted } from "@milaboratories/ts-helpers";
|
|
8
8
|
|
|
9
|
-
test(
|
|
9
|
+
test("check successful transaction", async () => {
|
|
10
10
|
const client = await getTestLLClient();
|
|
11
11
|
const tx = client.createTx(true);
|
|
12
12
|
|
|
13
|
-
const openResp = await tx.send(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
const openResp = await tx.send(
|
|
14
|
+
{
|
|
15
|
+
oneofKind: "txOpen",
|
|
16
|
+
txOpen: {
|
|
17
|
+
name: "test",
|
|
18
|
+
writable: TxAPI_Open_Request_WritableTx.WRITABLE,
|
|
19
|
+
enableFormattedErrors: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
false,
|
|
23
|
+
);
|
|
24
|
+
const commitResp = await tx.send(
|
|
25
|
+
{
|
|
26
|
+
oneofKind: "txCommit",
|
|
27
|
+
txCommit: {},
|
|
28
|
+
},
|
|
29
|
+
false,
|
|
30
|
+
);
|
|
21
31
|
|
|
22
32
|
expect(openResp.txOpen.tx?.isValid).toBeTruthy();
|
|
23
33
|
expect(commitResp.txCommit.success).toBeTruthy();
|
|
24
34
|
await tx.await();
|
|
25
35
|
});
|
|
26
36
|
|
|
27
|
-
test(
|
|
37
|
+
test("transaction timeout test", async () => {
|
|
28
38
|
const client = await getTestLLClient();
|
|
29
39
|
const tx = client.createTx(true, { timeout: 500 });
|
|
30
40
|
|
|
31
41
|
await expect(async () => {
|
|
32
42
|
const response = await tx.send(
|
|
33
43
|
{
|
|
34
|
-
oneofKind:
|
|
35
|
-
txOpen: {
|
|
44
|
+
oneofKind: "txOpen",
|
|
45
|
+
txOpen: {
|
|
46
|
+
name: "test",
|
|
47
|
+
writable: TxAPI_Open_Request_WritableTx.WRITABLE,
|
|
48
|
+
enableFormattedErrors: false,
|
|
49
|
+
},
|
|
36
50
|
},
|
|
37
|
-
false
|
|
51
|
+
false,
|
|
38
52
|
);
|
|
39
53
|
expect(response.txOpen.tx?.isValid).toBeTruthy();
|
|
40
54
|
await tx.await();
|
|
41
55
|
}).rejects.toThrow(Aborted);
|
|
42
56
|
});
|
|
43
57
|
|
|
44
|
-
test(
|
|
58
|
+
test("check timeout error type (passive)", async () => {
|
|
45
59
|
const client = await getTestLLClient();
|
|
46
60
|
const tx = client.createTx(true, { timeout: 500 });
|
|
47
61
|
|
|
48
62
|
try {
|
|
49
63
|
const response = await tx.send(
|
|
50
64
|
{
|
|
51
|
-
oneofKind:
|
|
52
|
-
txOpen: {
|
|
65
|
+
oneofKind: "txOpen",
|
|
66
|
+
txOpen: {
|
|
67
|
+
name: "test",
|
|
68
|
+
writable: TxAPI_Open_Request_WritableTx.WRITABLE,
|
|
69
|
+
enableFormattedErrors: false,
|
|
70
|
+
},
|
|
53
71
|
},
|
|
54
|
-
false
|
|
72
|
+
false,
|
|
55
73
|
);
|
|
56
74
|
expect(response.txOpen.tx?.isValid).toBeTruthy();
|
|
57
75
|
await tx.await();
|
|
@@ -60,17 +78,21 @@ test('check timeout error type (passive)', async () => {
|
|
|
60
78
|
}
|
|
61
79
|
});
|
|
62
80
|
|
|
63
|
-
test(
|
|
81
|
+
test("check timeout error type (active)", async () => {
|
|
64
82
|
const client = await getTestLLClient();
|
|
65
83
|
const tx = client.createTx(true, { timeout: 500 });
|
|
66
84
|
|
|
67
85
|
try {
|
|
68
86
|
const openResponse = await tx.send(
|
|
69
87
|
{
|
|
70
|
-
oneofKind:
|
|
71
|
-
txOpen: {
|
|
88
|
+
oneofKind: "txOpen",
|
|
89
|
+
txOpen: {
|
|
90
|
+
name: "test",
|
|
91
|
+
writable: TxAPI_Open_Request_WritableTx.WRITABLE,
|
|
92
|
+
enableFormattedErrors: false,
|
|
93
|
+
},
|
|
72
94
|
},
|
|
73
|
-
false
|
|
95
|
+
false,
|
|
74
96
|
);
|
|
75
97
|
expect(openResponse.txOpen.tx?.isValid).toBeTruthy();
|
|
76
98
|
|
|
@@ -82,30 +104,30 @@ test('check timeout error type (active)', async () => {
|
|
|
82
104
|
(Math.random() * 256) & 0xff,
|
|
83
105
|
(Math.random() * 256) & 0xff,
|
|
84
106
|
(Math.random() * 256) & 0xff,
|
|
85
|
-
(Math.random() * 256) & 0xff
|
|
107
|
+
(Math.random() * 256) & 0xff,
|
|
86
108
|
]);
|
|
87
109
|
|
|
88
110
|
const createResponse = await tx.send(
|
|
89
111
|
{
|
|
90
|
-
oneofKind:
|
|
112
|
+
oneofKind: "resourceCreateValue",
|
|
91
113
|
resourceCreateValue: {
|
|
92
114
|
id: createLocalResourceId(false, 1, 1),
|
|
93
|
-
type: { name:
|
|
115
|
+
type: { name: "TestValue", version: "1" },
|
|
94
116
|
data: rData,
|
|
95
|
-
errorIfExists: false
|
|
96
|
-
}
|
|
117
|
+
errorIfExists: false,
|
|
118
|
+
},
|
|
97
119
|
},
|
|
98
|
-
false
|
|
120
|
+
false,
|
|
99
121
|
);
|
|
100
122
|
const id = (await createResponse).resourceCreateValue.resourceId;
|
|
101
123
|
|
|
102
124
|
while (true) {
|
|
103
125
|
const vr = await tx.send(
|
|
104
126
|
{
|
|
105
|
-
oneofKind:
|
|
106
|
-
resourceGet: { resourceId: id, loadFields: false }
|
|
127
|
+
oneofKind: "resourceGet",
|
|
128
|
+
resourceGet: { resourceId: id, loadFields: false },
|
|
107
129
|
},
|
|
108
|
-
false
|
|
130
|
+
false,
|
|
109
131
|
);
|
|
110
132
|
|
|
111
133
|
expect(Buffer.compare(vr.resourceGet.resource!.data, rData)).toBe(0);
|
|
@@ -115,17 +137,21 @@ test('check timeout error type (active)', async () => {
|
|
|
115
137
|
}
|
|
116
138
|
});
|
|
117
139
|
|
|
118
|
-
test(
|
|
140
|
+
test("check is abort error (active)", async () => {
|
|
119
141
|
const client = await getTestLLClient();
|
|
120
142
|
const tx = client.createTx(true, { abortSignal: AbortSignal.timeout(100) });
|
|
121
143
|
|
|
122
144
|
try {
|
|
123
145
|
const openResponse = await tx.send(
|
|
124
146
|
{
|
|
125
|
-
oneofKind:
|
|
126
|
-
txOpen: {
|
|
147
|
+
oneofKind: "txOpen",
|
|
148
|
+
txOpen: {
|
|
149
|
+
name: "test",
|
|
150
|
+
writable: TxAPI_Open_Request_WritableTx.WRITABLE,
|
|
151
|
+
enableFormattedErrors: false,
|
|
152
|
+
},
|
|
127
153
|
},
|
|
128
|
-
false
|
|
154
|
+
false,
|
|
129
155
|
);
|
|
130
156
|
expect(openResponse.txOpen.tx?.isValid).toBeTruthy();
|
|
131
157
|
|
|
@@ -137,30 +163,30 @@ test('check is abort error (active)', async () => {
|
|
|
137
163
|
Math.random() & 0xff,
|
|
138
164
|
Math.random() & 0xff,
|
|
139
165
|
Math.random() & 0xff,
|
|
140
|
-
Math.random() & 0xff
|
|
166
|
+
Math.random() & 0xff,
|
|
141
167
|
]);
|
|
142
168
|
|
|
143
169
|
const createResponse = await tx.send(
|
|
144
170
|
{
|
|
145
|
-
oneofKind:
|
|
171
|
+
oneofKind: "resourceCreateValue",
|
|
146
172
|
resourceCreateValue: {
|
|
147
173
|
id: createLocalResourceId(false, 1, 1),
|
|
148
|
-
type: { name:
|
|
174
|
+
type: { name: "TestValue", version: "1" },
|
|
149
175
|
data: rData,
|
|
150
|
-
errorIfExists: false
|
|
151
|
-
}
|
|
176
|
+
errorIfExists: false,
|
|
177
|
+
},
|
|
152
178
|
},
|
|
153
|
-
false
|
|
179
|
+
false,
|
|
154
180
|
);
|
|
155
181
|
const id = (await createResponse).resourceCreateValue.resourceId;
|
|
156
182
|
|
|
157
183
|
while (true) {
|
|
158
184
|
const vr = await tx.send(
|
|
159
185
|
{
|
|
160
|
-
oneofKind:
|
|
161
|
-
resourceGet: { resourceId: id, loadFields: false }
|
|
186
|
+
oneofKind: "resourceGet",
|
|
187
|
+
resourceGet: { resourceId: id, loadFields: false },
|
|
162
188
|
},
|
|
163
|
-
false
|
|
189
|
+
false,
|
|
164
190
|
);
|
|
165
191
|
|
|
166
192
|
expect(Buffer.compare(vr.resourceGet.resource!.data, rData)).toBe(0);
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
TxAPI_ClientMessage,
|
|
3
3
|
TxAPI_ServerMessage,
|
|
4
|
-
} from
|
|
5
|
-
import type { BiDiStream } from
|
|
6
|
-
import Denque from
|
|
7
|
-
import type { Status } from
|
|
4
|
+
} from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api";
|
|
5
|
+
import type { BiDiStream } from "./abstract_stream";
|
|
6
|
+
import Denque from "denque";
|
|
7
|
+
import type { Status } from "../proto-grpc/github.com/googleapis/googleapis/google/rpc/status";
|
|
8
8
|
import {
|
|
9
9
|
PlErrorCodeNotFound,
|
|
10
10
|
RecoverablePlError,
|
|
11
11
|
rethrowMeaningfulError,
|
|
12
12
|
UnrecoverablePlError,
|
|
13
|
-
} from
|
|
14
|
-
import { StatefulPromise } from
|
|
13
|
+
} from "./errors";
|
|
14
|
+
import { StatefulPromise } from "./StatefulPromise";
|
|
15
15
|
|
|
16
|
-
export type ClientMessageRequest = TxAPI_ClientMessage[
|
|
16
|
+
export type ClientMessageRequest = TxAPI_ClientMessage["request"];
|
|
17
17
|
|
|
18
|
-
export type ServerMessageResponse = TxAPI_ServerMessage[
|
|
18
|
+
export type ServerMessageResponse = TxAPI_ServerMessage["response"];
|
|
19
19
|
|
|
20
20
|
type TxStream = BiDiStream<TxAPI_ClientMessage, TxAPI_ServerMessage>;
|
|
21
21
|
|
|
22
|
-
export type OneOfKind<T extends { oneofKind: unknown }, Kind extends T[
|
|
22
|
+
export type OneOfKind<T extends { oneofKind: unknown }, Kind extends T["oneofKind"]> = Extract<
|
|
23
23
|
T,
|
|
24
24
|
{ oneofKind: Kind }
|
|
25
25
|
>;
|
|
26
26
|
|
|
27
|
-
interface SingleResponseHandler<Kind extends ServerMessageResponse[
|
|
27
|
+
interface SingleResponseHandler<Kind extends ServerMessageResponse["oneofKind"]> {
|
|
28
28
|
kind: Kind;
|
|
29
29
|
expectMultiResponse: false;
|
|
30
30
|
resolve: (v: OneOfKind<ServerMessageResponse, Kind>) => void;
|
|
31
31
|
reject: (e: Error) => void;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
interface MultiResponseHandler<Kind extends ServerMessageResponse[
|
|
34
|
+
interface MultiResponseHandler<Kind extends ServerMessageResponse["oneofKind"]> {
|
|
35
35
|
kind: Kind;
|
|
36
36
|
expectMultiResponse: true;
|
|
37
37
|
resolve: (v: OneOfKind<ServerMessageResponse, Kind>[]) => void;
|
|
38
38
|
reject: (e: Error) => void;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
type AnySingleResponseHandler = SingleResponseHandler<ServerMessageResponse[
|
|
41
|
+
type AnySingleResponseHandler = SingleResponseHandler<ServerMessageResponse["oneofKind"]>;
|
|
42
42
|
|
|
43
|
-
type AnyMultiResponseHandler = MultiResponseHandler<ServerMessageResponse[
|
|
43
|
+
type AnyMultiResponseHandler = MultiResponseHandler<ServerMessageResponse["oneofKind"]>;
|
|
44
44
|
|
|
45
45
|
type AnyResponseHandler =
|
|
46
|
-
| SingleResponseHandler<ServerMessageResponse[
|
|
47
|
-
| MultiResponseHandler<ServerMessageResponse[
|
|
46
|
+
| SingleResponseHandler<ServerMessageResponse["oneofKind"]>
|
|
47
|
+
| MultiResponseHandler<ServerMessageResponse["oneofKind"]>;
|
|
48
48
|
|
|
49
|
-
function createResponseHandler<Kind extends ServerMessageResponse[
|
|
49
|
+
function createResponseHandler<Kind extends ServerMessageResponse["oneofKind"]>(
|
|
50
50
|
kind: Kind,
|
|
51
51
|
expectMultiResponse: boolean,
|
|
52
52
|
resolve:
|
|
@@ -62,9 +62,9 @@ function isRecoverable(status: Status): boolean {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
export class RethrowError extends Error {
|
|
65
|
-
name =
|
|
65
|
+
name = "RethrowError";
|
|
66
66
|
constructor(public readonly rethrowLambda: () => never) {
|
|
67
|
-
super(
|
|
67
|
+
super("Rethrow error, you should never see this one.");
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -166,7 +166,7 @@ export class LLPlTransaction {
|
|
|
166
166
|
|
|
167
167
|
if (message.multiMessage !== undefined && !message.multiMessage.isLast) {
|
|
168
168
|
this.assignErrorFactoryIfNotSet(() => {
|
|
169
|
-
throw new Error(
|
|
169
|
+
throw new Error("Unexpected message sequence.");
|
|
170
170
|
});
|
|
171
171
|
break;
|
|
172
172
|
}
|
|
@@ -185,8 +185,8 @@ export class LLPlTransaction {
|
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
if (
|
|
188
|
-
currentHandler.kind !== message.response.oneofKind
|
|
189
|
-
|
|
188
|
+
currentHandler.kind !== message.response.oneofKind &&
|
|
189
|
+
message?.multiMessage?.isEmpty !== true
|
|
190
190
|
) {
|
|
191
191
|
const errorMessage = `inconsistent request response types: ${currentHandler.kind} !== ${message.response.oneofKind}`;
|
|
192
192
|
|
|
@@ -266,7 +266,7 @@ export class LLPlTransaction {
|
|
|
266
266
|
const handler = this.responseHandlerQueue.shift();
|
|
267
267
|
if (!handler) break;
|
|
268
268
|
if (this.errorFactory) handler.reject(new RethrowError(this.errorFactory));
|
|
269
|
-
else handler.reject(new Error(
|
|
269
|
+
else handler.reject(new Error("no reply"));
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
// closing outgoing stream
|
|
@@ -292,29 +292,31 @@ export class LLPlTransaction {
|
|
|
292
292
|
if (processingResult !== null) processingResult();
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
public async send<Kind extends ClientMessageRequest[
|
|
295
|
+
public async send<Kind extends ClientMessageRequest["oneofKind"]>(
|
|
296
296
|
r: OneOfKind<ClientMessageRequest, Kind>,
|
|
297
|
-
expectMultiResponse: false
|
|
297
|
+
expectMultiResponse: false,
|
|
298
298
|
): Promise<OneOfKind<ServerMessageResponse, Kind>>;
|
|
299
|
-
public async send<Kind extends ClientMessageRequest[
|
|
299
|
+
public async send<Kind extends ClientMessageRequest["oneofKind"]>(
|
|
300
300
|
r: OneOfKind<ClientMessageRequest, Kind>,
|
|
301
|
-
expectMultiResponse: true
|
|
301
|
+
expectMultiResponse: true,
|
|
302
302
|
): Promise<OneOfKind<ServerMessageResponse, Kind>[]>;
|
|
303
303
|
/** Generate proper client message and send it to the server, and returns a promise of future response. */
|
|
304
|
-
public async send<Kind extends ClientMessageRequest[
|
|
304
|
+
public async send<Kind extends ClientMessageRequest["oneofKind"]>(
|
|
305
305
|
r: OneOfKind<ClientMessageRequest, Kind>,
|
|
306
306
|
expectMultiResponse: boolean,
|
|
307
307
|
): Promise<OneOfKind<ServerMessageResponse, Kind> | OneOfKind<ServerMessageResponse, Kind>[]> {
|
|
308
308
|
if (this.errorFactory) return Promise.reject(new RethrowError(this.errorFactory));
|
|
309
309
|
|
|
310
|
-
if (this.closed) return Promise.reject(new Error(
|
|
310
|
+
if (this.closed) return Promise.reject(new Error("Transaction already closed"));
|
|
311
311
|
|
|
312
312
|
// Note: Promise synchronously executes a callback passed to a constructor
|
|
313
|
-
const result = StatefulPromise.fromDeferredReject(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
const result = StatefulPromise.fromDeferredReject(
|
|
314
|
+
new Promise<OneOfKind<ServerMessageResponse, Kind>>((resolve, reject) => {
|
|
315
|
+
this.responseHandlerQueue.push(
|
|
316
|
+
createResponseHandler(r.oneofKind, expectMultiResponse, resolve, reject),
|
|
317
|
+
);
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
318
320
|
|
|
319
321
|
// Awaiting message dispatch to catch any associated errors.
|
|
320
322
|
// There is no hurry, we are not going to receive a response until message is sent.
|
|
@@ -327,7 +329,7 @@ export class LLPlTransaction {
|
|
|
327
329
|
return await result;
|
|
328
330
|
} catch (e: any) {
|
|
329
331
|
if (e instanceof RethrowError) e.rethrowLambda();
|
|
330
|
-
throw new Error(
|
|
332
|
+
throw new Error("Error while waiting for response", { cause: e });
|
|
331
333
|
}
|
|
332
334
|
}
|
|
333
335
|
|
|
@@ -342,6 +344,6 @@ export class LLPlTransaction {
|
|
|
342
344
|
|
|
343
345
|
private isTerminalResponse(message: TxAPI_ServerMessage): boolean {
|
|
344
346
|
const kind = message.response.oneofKind;
|
|
345
|
-
return kind ===
|
|
347
|
+
return kind === "txCommit" || kind === "txDiscard";
|
|
346
348
|
}
|
|
347
349
|
}
|
package/src/core/stat.ts
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
import { withTempRoot } from
|
|
2
|
-
import { StructTestResource, ValueTestResource } from
|
|
3
|
-
import { field, toGlobalFieldId, toGlobalResourceId } from
|
|
4
|
-
import { RecoverablePlError } from
|
|
5
|
-
import * as tp from
|
|
6
|
-
import { test, expect } from
|
|
7
|
-
import { StatefulPromise } from
|
|
8
|
-
|
|
9
|
-
test(
|
|
1
|
+
import { withTempRoot } from "../test/test_config";
|
|
2
|
+
import { StructTestResource, ValueTestResource } from "../helpers/pl";
|
|
3
|
+
import { field, toGlobalFieldId, toGlobalResourceId } from "./transaction";
|
|
4
|
+
import { RecoverablePlError } from "./errors";
|
|
5
|
+
import * as tp from "node:timers/promises";
|
|
6
|
+
import { test, expect } from "vitest";
|
|
7
|
+
import { StatefulPromise } from "./StatefulPromise";
|
|
8
|
+
|
|
9
|
+
test("get field", async () => {
|
|
10
10
|
await withTempRoot(async (pl) => {
|
|
11
|
-
const [rr0, theField1] = await pl.withWriteTx(
|
|
11
|
+
const [rr0, theField1] = await pl.withWriteTx("resource1", async (tx) => {
|
|
12
12
|
const r0 = tx.createStruct(StructTestResource);
|
|
13
13
|
const r1 = tx.createStruct(StructTestResource);
|
|
14
|
-
const f0 = { resourceId: tx.clientRoot, fieldName:
|
|
15
|
-
const f1 = { resourceId: tx.clientRoot, fieldName:
|
|
14
|
+
const f0 = { resourceId: tx.clientRoot, fieldName: "test0" };
|
|
15
|
+
const f1 = { resourceId: tx.clientRoot, fieldName: "test1" };
|
|
16
16
|
|
|
17
|
-
tx.createField(f0,
|
|
18
|
-
tx.createField(f1,
|
|
17
|
+
tx.createField(f0, "Dynamic");
|
|
18
|
+
tx.createField(f1, "Dynamic");
|
|
19
19
|
tx.setField(f0, r0);
|
|
20
20
|
tx.setField(f1, r1);
|
|
21
21
|
|
|
22
|
-
const theField1 = { resourceId: r1, fieldName:
|
|
23
|
-
tx.createField(theField1,
|
|
22
|
+
const theField1 = { resourceId: r1, fieldName: "theField" };
|
|
23
|
+
tx.createField(theField1, "Input");
|
|
24
24
|
tx.lock(r1);
|
|
25
|
-
tx.setField(theField1, tx.getFutureFieldValue(r0,
|
|
25
|
+
tx.setField(theField1, tx.getFutureFieldValue(r0, "theField", "Input"));
|
|
26
26
|
|
|
27
27
|
await tx.commit();
|
|
28
28
|
return [await r0.globalId, await toGlobalFieldId(theField1)];
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
const theField0 = { resourceId: rr0, fieldName:
|
|
31
|
+
const theField0 = { resourceId: rr0, fieldName: "theField" };
|
|
32
32
|
|
|
33
|
-
let fieldState = await pl.withReadTx(
|
|
33
|
+
let fieldState = await pl.withReadTx("test", async (tx) => {
|
|
34
34
|
return await tx.getField(theField1);
|
|
35
35
|
});
|
|
36
|
-
expect(fieldState.status ===
|
|
36
|
+
expect(fieldState.status === "Empty" || fieldState.status === "Assigned").toBe(true);
|
|
37
37
|
|
|
38
|
-
await pl.withWriteTx(
|
|
39
|
-
tx.createField(theField0,
|
|
38
|
+
await pl.withWriteTx("resource1", async (tx) => {
|
|
39
|
+
tx.createField(theField0, "Input");
|
|
40
40
|
tx.lock(rr0);
|
|
41
|
-
tx.setField(theField0, tx.createValue(ValueTestResource, Buffer.from(
|
|
41
|
+
tx.setField(theField0, tx.createValue(ValueTestResource, Buffer.from("hello")));
|
|
42
42
|
await tx.commit();
|
|
43
43
|
return theField0;
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
while (true) {
|
|
47
|
-
fieldState = await pl.withReadTx(
|
|
47
|
+
fieldState = await pl.withReadTx("test", async (tx) => {
|
|
48
48
|
return await tx.getField(theField1);
|
|
49
49
|
});
|
|
50
|
-
if (fieldState.status ===
|
|
50
|
+
if (fieldState.status === "Resolved") break;
|
|
51
51
|
await tp.setTimeout(10);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
test(
|
|
56
|
+
test("handle absent resource error", async () => {
|
|
57
57
|
await withTempRoot(async (pl) => {
|
|
58
|
-
const [rr0, ff0] = await pl.withWriteTx(
|
|
58
|
+
const [rr0, ff0] = await pl.withWriteTx("testCreateResource", async (tx) => {
|
|
59
59
|
const r0 = tx.createStruct(StructTestResource);
|
|
60
|
-
const f0 = { resourceId: tx.clientRoot, fieldName:
|
|
60
|
+
const f0 = { resourceId: tx.clientRoot, fieldName: "test0" };
|
|
61
61
|
|
|
62
|
-
tx.createField(f0,
|
|
62
|
+
tx.createField(f0, "Dynamic");
|
|
63
63
|
tx.setField(f0, r0);
|
|
64
64
|
|
|
65
65
|
await tx.commit();
|
|
@@ -67,18 +67,18 @@ test('handle absent resource error', async () => {
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
await pl.withWriteTx(
|
|
70
|
-
|
|
70
|
+
"testDeleteResource",
|
|
71
71
|
async (tx) => {
|
|
72
72
|
await tx.getResourceData(rr0, true);
|
|
73
73
|
tx.removeField(ff0);
|
|
74
74
|
await tx.commit();
|
|
75
75
|
},
|
|
76
|
-
{ sync: true }
|
|
76
|
+
{ sync: true },
|
|
77
77
|
);
|
|
78
78
|
|
|
79
79
|
StatefulPromise.debug = true;
|
|
80
80
|
|
|
81
|
-
let rState = await pl.withReadTx(
|
|
81
|
+
let rState = await pl.withReadTx("testRetrieveResource", async (tx) => {
|
|
82
82
|
await expect(async () => {
|
|
83
83
|
await tx.getResourceData(rr0, true);
|
|
84
84
|
}).rejects.toThrow(RecoverablePlError);
|
|
@@ -89,7 +89,7 @@ test('handle absent resource error', async () => {
|
|
|
89
89
|
|
|
90
90
|
expect(rState.fields).toHaveLength(0);
|
|
91
91
|
|
|
92
|
-
rState = await pl.withReadTx(
|
|
92
|
+
rState = await pl.withReadTx("testRetrieveResource", async (tx) => {
|
|
93
93
|
await expect(async () => {
|
|
94
94
|
await tx.listKeyValues(rr0);
|
|
95
95
|
}).rejects.toThrow(RecoverablePlError);
|
|
@@ -98,7 +98,7 @@ test('handle absent resource error', async () => {
|
|
|
98
98
|
|
|
99
99
|
expect(rState.fields).toHaveLength(0);
|
|
100
100
|
|
|
101
|
-
rState = await pl.withReadTx(
|
|
101
|
+
rState = await pl.withReadTx("testRetrieveResource", async (tx) => {
|
|
102
102
|
await expect(async () => {
|
|
103
103
|
await tx.getField(ff0);
|
|
104
104
|
}).rejects.toThrow(RecoverablePlError);
|
|
@@ -107,72 +107,72 @@ test('handle absent resource error', async () => {
|
|
|
107
107
|
|
|
108
108
|
expect(rState.fields).toHaveLength(0);
|
|
109
109
|
|
|
110
|
-
await pl.withReadTx(
|
|
110
|
+
await pl.withReadTx("testFieldAbsent", async (tx) => {
|
|
111
111
|
expect(await tx.getFieldIfExists(ff0)).toBeUndefined();
|
|
112
112
|
});
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
-
test(
|
|
116
|
+
test("handle KV storage", async () => {
|
|
117
117
|
await withTempRoot(async (pl) => {
|
|
118
|
-
await pl.withWriteTx(
|
|
119
|
-
tx.setKValue(tx.clientRoot,
|
|
120
|
-
tx.setKValue(tx.clientRoot,
|
|
118
|
+
await pl.withWriteTx("writeKV", async (tx) => {
|
|
119
|
+
tx.setKValue(tx.clientRoot, "a", "a");
|
|
120
|
+
tx.setKValue(tx.clientRoot, "b", "b");
|
|
121
121
|
await tx.commit();
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
-
await pl.withReadTx(
|
|
125
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
126
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
124
|
+
await pl.withReadTx("testReadIndividual", async (tx) => {
|
|
125
|
+
expect(await tx.getKValueString(tx.clientRoot, "a")).toEqual("a");
|
|
126
|
+
expect(await tx.getKValueString(tx.clientRoot, "b")).toEqual("b");
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
await pl.withReadTx(
|
|
130
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
131
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
129
|
+
await pl.withReadTx("testReadIndividualAndList", async (tx) => {
|
|
130
|
+
expect(await tx.getKValueString(tx.clientRoot, "a")).toEqual("a");
|
|
131
|
+
expect(await tx.getKValueString(tx.clientRoot, "b")).toEqual("b");
|
|
132
132
|
expect(await tx.listKeyValuesString(tx.clientRoot)).toEqual([
|
|
133
|
-
{ key:
|
|
134
|
-
{ key:
|
|
133
|
+
{ key: "a", value: "a" },
|
|
134
|
+
{ key: "b", value: "b" },
|
|
135
135
|
]);
|
|
136
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
137
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
136
|
+
expect(await tx.getKValueString(tx.clientRoot, "a")).toEqual("a");
|
|
137
|
+
expect(await tx.getKValueString(tx.clientRoot, "b")).toEqual("b");
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
await pl.withWriteTx(
|
|
141
|
-
tx.deleteKValue(tx.clientRoot,
|
|
140
|
+
await pl.withWriteTx("deleteKV", async (tx) => {
|
|
141
|
+
tx.deleteKValue(tx.clientRoot, "a");
|
|
142
142
|
await tx.commit();
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
-
await pl.withReadTx(
|
|
146
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
147
|
-
expect(await tx.listKeyValuesString(tx.clientRoot)).toEqual([{ key:
|
|
148
|
-
expect(await tx.getKValueString(tx.clientRoot,
|
|
145
|
+
await pl.withReadTx("testReadIndividualAndList2", async (tx) => {
|
|
146
|
+
expect(await tx.getKValueString(tx.clientRoot, "b")).toEqual("b");
|
|
147
|
+
expect(await tx.listKeyValuesString(tx.clientRoot)).toEqual([{ key: "b", value: "b" }]);
|
|
148
|
+
expect(await tx.getKValueString(tx.clientRoot, "b")).toEqual("b");
|
|
149
149
|
});
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
-
test(
|
|
153
|
+
test("handle empty KV storage", async () => {
|
|
154
154
|
await withTempRoot(async (pl) => {
|
|
155
|
-
await pl.withReadTx(
|
|
155
|
+
await pl.withReadTx("testReadIndividualAndList", async (tx) => {
|
|
156
156
|
expect(await tx.listKeyValuesString(tx.clientRoot)).toEqual([]);
|
|
157
157
|
});
|
|
158
158
|
});
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
-
test(
|
|
161
|
+
test("handle KV storage 2", async () => {
|
|
162
162
|
await withTempRoot(async (pl) => {
|
|
163
|
-
const r1 = await pl.withWriteTx(
|
|
163
|
+
const r1 = await pl.withWriteTx("writeKV", async (tx) => {
|
|
164
164
|
const rr1 = tx.createEphemeral(StructTestResource);
|
|
165
|
-
tx.createField(field(rr1,
|
|
166
|
-
tx.setKValue(rr1,
|
|
167
|
-
tx.setKValue(rr1,
|
|
165
|
+
tx.createField(field(rr1, "a"), "Dynamic", rr1);
|
|
166
|
+
tx.setKValue(rr1, "a", "a");
|
|
167
|
+
tx.setKValue(rr1, "b", "b");
|
|
168
168
|
await tx.commit();
|
|
169
169
|
return await toGlobalResourceId(rr1);
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
-
await pl.withReadTx(
|
|
172
|
+
await pl.withReadTx("testReadIndividualAndList", async (tx) => {
|
|
173
173
|
expect(await tx.listKeyValuesString(r1)).toEqual([
|
|
174
|
-
{ key:
|
|
175
|
-
{ key:
|
|
174
|
+
{ key: "a", value: "a" },
|
|
175
|
+
{ key: "b", value: "b" },
|
|
176
176
|
]);
|
|
177
177
|
});
|
|
178
178
|
});
|