Skip to content

Commit a190407

Browse files
committed
Implement RFC 021 Projections api
- Create: - Rename `createContinuousProjection` to `createProjection` - Remove `createOneTimeProjection` - Remove `createTransientProjection` - List: - Rename `listContinuousProjection` to `listProjection` - Remove `listOneTimeProjection` - Remove `listTransientProjection` - Details: - remove `mode` from `ProjectionDetails` - delete `CONTINUOUS` `ONE_TIME` & `TRANSIENT` constants - Update: - Rename `trackEmittedStreams` to `emitEnabled` (Was incorrectly named, `trackEmittedStreams` to be added in future version.) - Reset: - remove `writeCheckpoint` option (had no effect) - Disable: - In `disableProjection` remove `writeCheckpoint` option. (Always true) - Add `abortProjection` method. (`writeCheckpoint` always false) - Tests: - Update tests to match updated behaviour - Gate fuzzy disable test matching behind server version, for stricter tests on known good server implementations - Samples: - Update samples to match new API
1 parent f9de3ba commit a190407

26 files changed

+202
-561
lines changed

Diff for: samples/projection-management.ts

+15-29
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe("[sample] projection-management", () => {
1717
retry = 5
1818
): Promise<string> => {
1919
try {
20-
await client.createContinuousProjection(name, "fromAll().when()");
20+
await client.createProjection(name, "fromAll().when()");
2121
} catch (error) {
2222
if (retry > 0) return createTestProjection(name, retry - 1);
2323
throw error;
@@ -79,12 +79,12 @@ describe("[sample] projection-management", () => {
7979
})
8080
.outputState();
8181
`;
82-
await client.createContinuousProjection(name, projection);
82+
await client.createProjection(name, projection);
8383
// endregion CreateContinuous
8484

8585
// region CreateContinuous_Conflict
8686
try {
87-
await client.createContinuousProjection(name, projection);
87+
await client.createProjection(name, projection);
8888
} catch (err) {
8989
if (!isCommandError(err) || !err.message.includes("Conflict")) throw err;
9090
console.log(`${name} already exists`);
@@ -138,14 +138,12 @@ describe("[sample] projection-management", () => {
138138
const name = await createTestProjection();
139139

140140
// before https://github.com/EventStore/EventStore/pull/2944
141-
// writeCheckpoint had to be false to stop the projection
142-
await client.disableProjection(name, {
143-
writeCheckpoint: false,
144-
});
141+
// writeCheckpoint had to be false (abort) to stop the projection
142+
await client.abortProjection(name);
145143

146144
// region Delete
147145
// A projection must be disabled to allow it to be deleted.
148-
await client.disableProjection(name, { writeCheckpoint: true });
146+
await client.disableProjection(name);
149147

150148
// The projection can now be deleted
151149
await client.deleteProjection(name);
@@ -170,10 +168,7 @@ describe("[sample] projection-management", () => {
170168
const name = await createTestProjection();
171169

172170
// region Abort
173-
await client.disableProjection(name, {
174-
// not writing the checkpoint will abort the projection
175-
writeCheckpoint: false,
176-
});
171+
await client.abortProjection(name);
177172
// endregion Abort
178173
});
179174

@@ -182,9 +177,7 @@ describe("[sample] projection-management", () => {
182177
const projectionName = "projection that does not exist";
183178

184179
try {
185-
await client.disableProjection(projectionName, {
186-
writeCheckpoint: false,
187-
});
180+
await client.abortProjection(projectionName);
188181
} catch (err) {
189182
if (!isCommandError(err) || !err.message.includes("NotFound")) throw err;
190183
console.log(`${projectionName} does not exist`);
@@ -232,7 +225,7 @@ describe("[sample] projection-management", () => {
232225
})
233226
.outputState();
234227
`;
235-
await client.createContinuousProjection(name, "fromAll().when()");
228+
await client.createProjection(name, "fromAll().when()");
236229
await client.updateProjection(name, projection);
237230
// endregion Update
238231
});
@@ -259,16 +252,10 @@ describe("[sample] projection-management", () => {
259252

260253
test("ListContinuous", async () => {
261254
// region ListContinuous
262-
const projections = await client.listContinuousProjections();
263-
264-
for (const {
265-
name,
266-
status,
267-
checkpointStatus,
268-
mode,
269-
progress,
270-
} of projections) {
271-
console.log(name, status, checkpointStatus, mode, progress);
255+
const projections = await client.listProjections();
256+
257+
for (const { name, status, checkpointStatus, progress } of projections) {
258+
console.log(name, status, checkpointStatus, progress);
272259
}
273260
// endregion ListContinuous
274261
});
@@ -283,7 +270,6 @@ describe("[sample] projection-management", () => {
283270
projection.name,
284271
projection.status,
285272
projection.checkpointStatus,
286-
projection.mode,
287273
projection.progress
288274
);
289275
// endregion GetStatus
@@ -312,7 +298,7 @@ describe("[sample] projection-management", () => {
312298
.outputState();
313299
`;
314300

315-
await client.createContinuousProjection(name, projection);
301+
await client.createProjection(name, projection);
316302

317303
// Give it some time to count event
318304
await delay(500);
@@ -345,7 +331,7 @@ describe("[sample] projection-management", () => {
345331
.outputState();
346332
`;
347333

348-
await client.createContinuousProjection(name, projection);
334+
await client.createProjection(name, projection);
349335

350336
// Give it some time to have a result.
351337
await delay(500);

Diff for: src/__test__/projections/createOneTimeProjection.test.ts

-55
This file was deleted.

Diff for: src/__test__/projections/createContinuousProjection.test.ts renamed to src/__test__/projections/createProjection.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createTestNode } from "@test-utils";
22

33
import { EventStoreDBClient } from "@eventstore/db-client";
44

5-
describe("createContinuousProjection", () => {
5+
describe("createProjection", () => {
66
const node = createTestNode();
77
let client!: EventStoreDBClient;
88

@@ -23,7 +23,7 @@ describe("createContinuousProjection", () => {
2323
const PROJECTION_NAME = "track and field";
2424

2525
await expect(
26-
client.createContinuousProjection(
26+
client.createProjection(
2727
PROJECTION_NAME,
2828
`
2929
fromAll()
@@ -43,7 +43,7 @@ describe("createContinuousProjection", () => {
4343
test("do not track", async () => {
4444
const PROJECTION_NAME = "do not track";
4545
await expect(
46-
client.createContinuousProjection(
46+
client.createProjection(
4747
PROJECTION_NAME,
4848
`
4949
fromAll()

Diff for: src/__test__/projections/createTransientProjection.test.ts

-39
This file was deleted.

Diff for: src/__test__/projections/deleteProjection.test.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ describe("deleteProjection", () => {
4040
test("delete the projection", async () => {
4141
const PROJECTION_NAME = "projection_to_delete_everything";
4242

43-
await client.createContinuousProjection(PROJECTION_NAME, projection);
43+
await client.createProjection(PROJECTION_NAME, projection);
4444

4545
const beforeDetails = await client.getProjectionStatistics(PROJECTION_NAME);
4646

4747
expect(beforeDetails).toBeDefined();
4848
expect(beforeDetails.projectionStatus).toBe(RUNNING);
4949

50-
await client.disableProjection(PROJECTION_NAME, { writeCheckpoint: true });
50+
await client.disableProjection(PROJECTION_NAME);
5151

5252
const disabledDetails = await client.getProjectionStatistics(
5353
PROJECTION_NAME
@@ -62,9 +62,7 @@ describe("deleteProjection", () => {
6262
if (disabledDetails.projectionStatus === ABORTED) {
6363
// before https://github.com/EventStore/EventStore/pull/2944
6464
// writeCheckpoint had to be false to stop the projection
65-
await client.disableProjection(PROJECTION_NAME, {
66-
writeCheckpoint: false,
67-
});
65+
await client.abortProjection(PROJECTION_NAME);
6866

6967
const stoppedDetails = await client.getProjectionStatistics(
7068
PROJECTION_NAME

Diff for: src/__test__/projections/disableProjection.test.ts

+46-28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { createTestNode } from "@test-utils";
1+
/** @jest-environment ./src/__test__/utils/enableVersionCheck.ts */
2+
3+
import { createTestNode, matchServerVersion } from "@test-utils";
24

35
import {
46
ABORTED,
@@ -8,7 +10,7 @@ import {
810
UnknownError,
911
} from "@eventstore/db-client";
1012

11-
describe("disableProjection", () => {
13+
describe("disable / abort", () => {
1214
const node = createTestNode();
1315
let client!: EventStoreDBClient;
1416

@@ -36,11 +38,11 @@ describe("disableProjection", () => {
3638
await node.down();
3739
});
3840

39-
describe("disables the projection", () => {
40-
test("write a checkpoint", async () => {
41-
const PROJECTION_NAME = "projection_to_disable_with_checkpoint";
41+
describe("disableProjection", () => {
42+
test("disables the projection", async () => {
43+
const PROJECTION_NAME = "projection_to_disable";
4244

43-
await client.createContinuousProjection(PROJECTION_NAME, projection);
45+
await client.createProjection(PROJECTION_NAME, projection);
4446

4547
const beforeDetails = await client.getProjectionStatistics(
4648
PROJECTION_NAME
@@ -49,25 +51,39 @@ describe("disableProjection", () => {
4951
expect(beforeDetails).toBeDefined();
5052
expect(beforeDetails.projectionStatus).toBe(RUNNING);
5153

52-
await client.disableProjection(PROJECTION_NAME, {
53-
writeCheckpoint: true,
54-
});
54+
await client.disableProjection(PROJECTION_NAME);
5555

5656
const afterDetails = await client.getProjectionStatistics(
5757
PROJECTION_NAME
5858
);
5959

6060
expect(afterDetails).toBeDefined();
6161

62-
// Incorrect projection status was switched (ABORTED -> STOPPED) in
63-
// https://github.com/EventStore/EventStore/pull/2944
64-
expect([STOPPED, ABORTED]).toContain(afterDetails.projectionStatus);
62+
if (matchServerVersion`>=21.10`) {
63+
expect(afterDetails.projectionStatus).toBe(STOPPED);
64+
} else {
65+
// Incorrect projection status was switched (ABORTED -> STOPPED) in
66+
// https://github.com/EventStore/EventStore/pull/2944
67+
expect([STOPPED, ABORTED]).toContain(afterDetails.projectionStatus);
68+
}
69+
});
70+
});
71+
72+
describe("errors", () => {
73+
test("projection doesnt exist", async () => {
74+
const PROJECTION_NAME = "doesnt exist";
75+
76+
await expect(
77+
client.disableProjection(PROJECTION_NAME)
78+
).rejects.toThrowError(UnknownError); // https://github.com/EventStore/EventStore/issues/2732
6579
});
80+
});
6681

67-
test("do not write a checkpoint", async () => {
68-
const PROJECTION_NAME = "projection_to_disable_without_checkpoint";
82+
describe("abortProjection", () => {
83+
test("aborts the projection", async () => {
84+
const PROJECTION_NAME = "projection_to_abort";
6985

70-
await client.createContinuousProjection(PROJECTION_NAME, projection);
86+
await client.createProjection(PROJECTION_NAME, projection);
7187

7288
const beforeDetails = await client.getProjectionStatistics(
7389
PROJECTION_NAME
@@ -76,29 +92,31 @@ describe("disableProjection", () => {
7692
expect(beforeDetails).toBeDefined();
7793
expect(beforeDetails.projectionStatus).toBe(RUNNING);
7894

79-
await client.disableProjection(PROJECTION_NAME, {
80-
writeCheckpoint: false,
81-
});
95+
await client.abortProjection(PROJECTION_NAME);
8296

8397
const afterDetails = await client.getProjectionStatistics(
8498
PROJECTION_NAME
8599
);
86100

87101
expect(afterDetails).toBeDefined();
88102

89-
// Incorrect projection status was fixed (STOPPED -> ABORTED) in
90-
// https://github.com/EventStore/EventStore/pull/2944
91-
expect([ABORTED, STOPPED]).toContain(afterDetails.projectionStatus);
103+
if (matchServerVersion`>=21.10`) {
104+
expect(afterDetails.projectionStatus).toBe(ABORTED);
105+
} else {
106+
// Incorrect projection status was switched (ABORTED -> STOPPED) in
107+
// https://github.com/EventStore/EventStore/pull/2944
108+
expect([STOPPED, ABORTED]).toContain(afterDetails.projectionStatus);
109+
}
92110
});
93-
});
94111

95-
describe("errors", () => {
96-
test("projection doesnt exist", async () => {
97-
const PROJECTION_NAME = "doesnt exist";
112+
describe("errors", () => {
113+
test("projection doesnt exist", async () => {
114+
const PROJECTION_NAME = "doesnt exist";
98115

99-
await expect(
100-
client.disableProjection(PROJECTION_NAME)
101-
).rejects.toThrowError(UnknownError); // https://github.com/EventStore/EventStore/issues/2732
116+
await expect(
117+
client.abortProjection(PROJECTION_NAME)
118+
).rejects.toThrowError(UnknownError); // https://github.com/EventStore/EventStore/issues/2732
119+
});
102120
});
103121
});
104122
});

0 commit comments

Comments
 (0)