-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First collection of Restate patterns (#49)
- Loading branch information
1 parent
c337efe
commit ca40202
Showing
10 changed files
with
841 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Restate Sample Patterns | ||
|
||
A collections of useful patterns in distributed applications, and how to | ||
implement them with [Restate](https://github.com/restatedev/). | ||
This is a continuously evolving list. | ||
|
||
The patterns currently exist only in TypeScript/JavaScript, other languages | ||
will be added soon. | ||
|
||
All patterns are described in one file and have a comment block at the top | ||
that explains them. | ||
|
||
### List of Patterns | ||
|
||
* [**Durable Event-based Asynchronous Communication as RPC**](src/async_calls_as_rpc.ts) | ||
* [**Idempotency Tokens**](src/deterministic_idempotency_tokens.ts) | ||
* [**Single-writer Concurrency**](src/single_writer_concurrency.ts) | ||
* [**Dual Writes**](src/dual_writes.ts) | ||
* [**Distributed Locks**](src/distributed_locks.ts) | ||
* [**Idempotent DynamoDB Updates**](src/dynamo_db_idempotency.ts) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "restate-pattern-collection", | ||
"version": "0.0.1", | ||
"description": "A collection of useful patterns for distributed applications with Restate (https://github.com/restatedev/)", | ||
"type": "commonjs", | ||
"scripts": { | ||
"build": "tsc --noEmitOnError" | ||
}, | ||
"dependencies": { | ||
"@restatedev/restate-sdk": "^0.5.1" | ||
}, | ||
"devDependencies": { | ||
"typescript": "^5.0.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import * as restate from "@restatedev/restate-sdk"; | ||
|
||
// ----------------- ----------------- | ||
// Durable Event-based Asynchronous Communication as RPC | ||
// ----------------- ----------------- | ||
// | ||
// !!! Durability of communication end-to-end, without having to deal with !!! | ||
// !!! message queues and message sending semantics. !!! | ||
// | ||
// Calling asynchronously via sending events through a persistent message queue, | ||
// is very powerful, because it ensures the call happens regardless of failures | ||
// or temporary unavailability of caller or callee. | ||
// | ||
// Restate makes this a breeze: Its RPC construct is as simple as the req/resp | ||
// RPC that you know. But it is backed by durable event channels, and the durable | ||
// promises and durable execution make sure everything wires up correctly after | ||
// any failure. The ability to suspend when awaiting means that the caller | ||
// doesn't need to stay up while waiting for the callee's response. | ||
// | ||
// Additionally, also RPC calls from external clients to Restate-backed services | ||
// have durability of requests (even when the deployed service/handler is down, | ||
// the call will be delivered once the service comes back), and allow the caller | ||
// to resume / re-connect to invocations. | ||
|
||
|
||
// Reliably call / re-connect a call via | ||
// | ||
// curl -X POST http://<restate-runtime>/caller/makeCall \ | ||
// -H 'idempotency-key: ABC' | ||
// -H 'content-type: application/json' | ||
// -d '{"request": 12345}' | ||
// | ||
// can reconnect to this invocation by curl-ing with the same idempotency token again. | ||
|
||
|
||
const caller = { | ||
|
||
makeCall: async (ctx: restate.RpcContext, request: number) => { | ||
// this call happens asynchronous through a durable message channel | ||
// and completes reliably despite any caller or callee failure. | ||
// The caller can even suspend while waiting for the callee to respond. | ||
const result = await ctx.rpc(calleeApi).beCalled("hello " + request); | ||
|
||
// ... | ||
} | ||
} | ||
|
||
const callee = { | ||
beCalled: async (ctx: restate.RpcContext, arg: string) => { | ||
// this will reliably receive the call from 'caller' | ||
} | ||
} | ||
|
||
const calleeService = restate.router(callee); | ||
const calleeApi = { path: "callee" } as restate.ServiceApi<typeof calleeService>; | ||
|
||
const callerService = restate.router(caller); | ||
const callerApi = { path: "caller" } as restate.ServiceApi<typeof callerService>; | ||
|
||
restate | ||
.createServer() | ||
.bindRouter(calleeApi.path, calleeService) | ||
.bindRouter(callerApi.path, callerService) | ||
.listen(); |
Oops, something went wrong.