Skip to content

Commit

Permalink
Updated handle method processing for expected version
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed Sep 29, 2024
1 parent 7aabb29 commit 2a917c5
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 44 deletions.
68 changes: 56 additions & 12 deletions src/packages/pongo/src/core/collection/pongoCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import {
} from '@event-driven-io/dumbo';
import { v4 as uuid } from 'uuid';
import {
expectedVersionValue,
operationResult,
type CollectionOperationOptions,
type DeleteManyOptions,
type DeleteOneOptions,
type DocumentHandler,
type HandleOptions,
type InsertManyOptions,
type InsertOneOptions,
type OptionalUnlessRequiredIdAndVersion,
Expand All @@ -26,6 +28,7 @@ import {
type PongoDeleteResult,
type PongoDocument,
type PongoFilter,
type PongoHandleResult,
type PongoInsertManyResult,
type PongoInsertOneResult,
type PongoUpdate,
Expand All @@ -35,6 +38,7 @@ import {
type UpdateOneOptions,
type UpsertOneOptions,
type WithoutId,
type WithVersion,
} from '..';
import { pongoCollectionPostgreSQLMigrations } from '../../postgres';

Expand Down Expand Up @@ -347,34 +351,74 @@ export const pongoCollection = <
handle: async (
id: string,
handle: DocumentHandler<T>,
options?: CollectionOperationOptions,
): Promise<T | null> => {
options?: HandleOptions,
): Promise<PongoHandleResult<T>> => {
const { expectedVersion: version, ...operationOptions } = options ?? {};
await ensureCollectionCreated(options);

const byId: PongoFilter<T> = { _id: id };

const existing = await collection.findOne(byId, options);
const existing = (await collection.findOne(
byId,
options,
)) as WithVersion<T>;

const expectedVersion = expectedVersionValue(version);

if (
(existing == null && version === 'DOCUMENT_EXISTS') ||
(existing == null && expectedVersion != null) ||
(existing != null && version === 'DOCUMENT_DOES_NOT_EXIST') ||
(existing != null &&
expectedVersion !== null &&
existing._version !== expectedVersion)
) {
return operationResult<PongoHandleResult<T>>(
{
successful: false,
document: existing as T,
},
{ operationName: 'handle', collectionName, errors },
);
}

const result = await handle(existing);
const result = await handle(existing as T);

if (!existing && result) {
const newDoc = { ...result, _id: id };
await collection.insertOne(
const insertResult = await collection.insertOne(
{ ...newDoc, _id: id } as OptionalUnlessRequiredIdAndVersion<T>,
options,
{
...operationOptions,
expectedVersion: 'DOCUMENT_DOES_NOT_EXIST',
},
);
return newDoc;
return { ...insertResult, document: newDoc };
}

if (existing && !result) {
await collection.deleteOne(byId, options);
return null;
const deleteResult = await collection.deleteOne(byId, {
...operationOptions,
expectedVersion: expectedVersion ?? 'DOCUMENT_EXISTS',
});
return { ...deleteResult, document: null };
}

if (existing && result)
await collection.replaceOne(byId, result, options);
if (existing && result) {
const replaceResult = await collection.replaceOne(byId, result, {
...operationOptions,
expectedVersion: expectedVersion ?? 'DOCUMENT_EXISTS',
});
return { ...replaceResult, document: result };
}

return result;
return operationResult<PongoHandleResult<T>>(
{
successful: true,
document: existing as T,
},
{ operationName: 'handle', collectionName, errors },
);
},
find: async (
filter?: PongoFilter<T>,
Expand Down
14 changes: 12 additions & 2 deletions src/packages/pongo/src/core/typing/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ export type UpdateManyOptions = {
>;
} & CollectionOperationOptions;

export type HandleOptions = {
expectedVersion?: ExpectedDocumentVersion;
} & CollectionOperationOptions;

export type ReplaceOneOptions = {
expectedVersion?: Exclude<ExpectedDocumentVersion, 'DOCUMENT_DOES_NOT_EXIST'>;
} & CollectionOperationOptions;
Expand Down Expand Up @@ -191,8 +195,8 @@ export interface PongoCollection<T extends PongoDocument> {
handle(
id: string,
handle: DocumentHandler<T>,
options?: CollectionOperationOptions,
): Promise<T | null>;
options?: HandleOptions,
): Promise<PongoHandleResult<T>>;
readonly schema: Readonly<{
component: SchemaComponent;
migrate(): Promise<void>;
Expand Down Expand Up @@ -469,6 +473,12 @@ export interface PongoDeleteManyResult extends OperationResult {
deletedCount: number;
}

export type PongoHandleResult<T> =
| (PongoInsertOneResult & { document: T })
| (PongoUpdateResult & { document: T })
| (PongoDeleteResult & { document: null })
| (OperationResult & { document: null });

export type PongoDocument = Record<string, unknown>;

export type DocumentHandler<T extends PongoDocument> =
Expand Down
15 changes: 11 additions & 4 deletions src/packages/pongo/src/e2e/compatibilityTest.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,11 @@ void describe('MongoDB Compatibility Tests', () => {
const handle = (_existing: User | null) => newDoc;

const resultPongo = await pongoCollection.handle(nonExistingId, handle);
assert.deepStrictEqual(resultPongo, { ...newDoc, _id: nonExistingId });
assert(resultPongo.successful);
assert.deepStrictEqual(resultPongo.document, {
...newDoc,
_id: nonExistingId,
});

const pongoDoc = await pongoCollection.findOne({
_id: nonExistingId,
Expand Down Expand Up @@ -953,7 +957,8 @@ void describe('MongoDB Compatibility Tests', () => {
handle,
);

assert.deepStrictEqual(resultPongo, {
assert(resultPongo.successful);
assert.deepStrictEqual(resultPongo.document, {
...updatedDoc,
});

Expand Down Expand Up @@ -981,8 +986,9 @@ void describe('MongoDB Compatibility Tests', () => {
pongoInsertResult.insertedId,
handle,
);
assert(resultPongo.successful);

assert.strictEqual(resultPongo, null);
assert.strictEqual(resultPongo.document, null);

const pongoDoc = await pongoCollection.findOne({
_id: pongoInsertResult.insertedId,
Expand All @@ -1004,8 +1010,9 @@ void describe('MongoDB Compatibility Tests', () => {
pongoInsertResult.insertedId,
handle,
);
assert(resultPongo.successful);

assert.deepStrictEqual(resultPongo, {
assert.deepStrictEqual(resultPongo.document, {
...existingDoc,
_id: pongoInsertResult.insertedId,
_version: 1n,
Expand Down
15 changes: 11 additions & 4 deletions src/packages/pongo/src/e2e/postgres.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,11 @@ void describe('MongoDB Compatibility Tests', () => {
const handle = (_existing: User | null) => newDoc;

const resultPongo = await pongoCollection.handle(nonExistingId, handle);
assert.deepStrictEqual(resultPongo, { ...newDoc, _id: nonExistingId });
assert(resultPongo.successful);
assert.deepStrictEqual(resultPongo.document, {
...newDoc,
_id: nonExistingId,
});

const pongoDoc = await pongoCollection.findOne({
_id: nonExistingId,
Expand Down Expand Up @@ -1061,7 +1065,8 @@ void describe('MongoDB Compatibility Tests', () => {
handle,
);

assert.deepStrictEqual(resultPongo, {
assert(resultPongo.successful);
assert.deepStrictEqual(resultPongo.document, {
...updatedDoc,
});

Expand Down Expand Up @@ -1089,8 +1094,9 @@ void describe('MongoDB Compatibility Tests', () => {
pongoInsertResult.insertedId!,
handle,
);
assert(resultPongo.successful);

assert.strictEqual(resultPongo, null);
assert.strictEqual(resultPongo.document, null);

const pongoDoc = await pongoCollection.findOne({
_id: pongoInsertResult.insertedId!,
Expand All @@ -1113,7 +1119,8 @@ void describe('MongoDB Compatibility Tests', () => {
handle,
);

assert.deepStrictEqual(resultPongo, {
assert(resultPongo.successful);
assert.deepStrictEqual(resultPongo.document, {
...existingDoc,
_id: pongoInsertResult.insertedId,
_version: 1n,
Expand Down
Loading

0 comments on commit 2a917c5

Please sign in to comment.