Skip to content

Commit

Permalink
Merge pull request #26 from lifeomic/dynamo-stream-handler
Browse files Browse the repository at this point in the history
[Proposal] Introduce DynamoStreamHandler
  • Loading branch information
swain authored Mar 2, 2022
2 parents ce04651 + 9b6a93d commit 9f76f3e
Show file tree
Hide file tree
Showing 7 changed files with 978 additions and 8 deletions.
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,83 @@ process AWS data streams.
```bash
yarn add @lifeomic/delta
```

### `DynamoStreamHandler`

This helper provides an abstraction over a DynamoDB Stream Lambda handler.

```typescript
const stream = new DynamoStreamHandler({
logger,
unmarshall: (object) => {
/* ... unmarshall from unknown stream format -> your custom type ... */
return { id: object.id };
},
createRunContext: () => {
/* ... create the "context", e.g. data sources ... */
return { doSomething: () => null };
},
})
.onInsert(async (ctx, entity) => {
// INSERT actions receive a single strongly typed new entities
// (entities are typed based on the `unmarshall` function)
entity.id;

// `ctx` contains the nice result of `createRunContext`
await ctx.dataSources.doSomething();

// `ctx` contains a logger by default, which already includes niceties like
// the AWS request id
ctx.logger.info('blah blah');
})
// The API is chainable to help with readability
.onModify(async (ctx, oldEntity, newEntity) => {
// MODIFY actions receive strongly typed old + new entities
oldEntity.id;
newEntity.id;
})
.onRemove(async (ctx, oldEntity) => {
// REMOVE actions receive a single strongly typed old entity
oldEntity.id;

ctx.logger.info('first remove action');
})
// When multiple actions have been added for the same event (e.g. two `onRemove` calls),
// they are executed in.order.
.onRemove(async (ctx, oldEntity) => {
ctx.logger.info('second remove action');
});

// Provides a dead-simple API for creating the Lambda.
export const handler = stream.lambda();
```

`DynamoStreamHelper` also comes with a nice helper for testing: `harness(...)`

```typescript
const harness = stream.harness({
marshall: () => {
/* marshall from your custom type -> stream format */
},
/* optionally override the logger */
logger,
createRunContext: () => {
/* optionally override the context, to mock e.g. data sources */
}
})

test('something', async () => {
// Provides a simple `sendEvent` function
await harness.sendEvent({
records: [
// Simplified, strongly-typed event types for readability
{ type: 'remove', entity: ... },
{ type: 'insert', entity: ... },
{ type: 'modify', oldEntity: ..., newEntity: ... },
]
})

// Also provides access to the underlying run context for assertions + mocking
expect(harness.context.dataSources.doSomething).toHaveBeenCalled()
})
```
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,22 @@
"devDependencies": {
"@lifeomic/eslint-config-standards": "^2.1.1",
"@lifeomic/jest-config": "^1.1.2",
"@lifeomic/logging": "^4.0.0",
"@lifeomic/typescript-config": "^1.0.3",
"@types/jest": "^27.4.1",
"@types/uuid": "^8.3.4",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.4.0",
"jest": "^27.5.1",
"prettier": "^2.5.1",
"ts-jest": "^27.1.3",
"typescript": "^4.5.5"
"typescript": "^4.5.5",
"uuid": "^8.3.2"
},
"dependencies": {
"@types/aws-lambda": "^8.10.92"
},
"peerDependencies": {
"@lifeomic/logging": "*"
}
}
Loading

0 comments on commit 9f76f3e

Please sign in to comment.