Skip to content

Commit

Permalink
Add Protobuf sample (#113)
Browse files Browse the repository at this point in the history
* Update to 0.19.0

* Update update script

* Revert "Update to 0.19.0"

This reverts commit 7edc75e6c699609235b87844e82497ac76a95d61.

* Non-mono

* Mono

* Fix build

* Fix linting

* Update interceptors version

* Add protobuf sample

* Add generated files to .gitignore

* README and prettier

* Fix proto build

Was having this error during building:
protobufjs/protobuf.js#1368
  • Loading branch information
TRIPH925 committed Apr 3, 2022
1 parent 4c01692 commit 819b86a
Show file tree
Hide file tree
Showing 18 changed files with 230 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.eslintrc.js
.eslintrc.js
protobufs/protos/
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ node_modules
build
lib
.next
.vscode
.vscode
protobufs/protos/json-module.js
protobufs/protos/root.d.ts
14 changes: 10 additions & 4 deletions .scripts/copy-shared-files.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ const ADDITIONAL_SAMPLES = [];
// Some samples have different config files from those in .shared/
// that we don't want to overwrite
const TSCONFIG_EXCLUDE = ['nextjs-ecommerce-oneclick', 'monorepo-folders', 'fetch-esm', 'production', 'hello-world-js'];
const GITIGNORE_EXCLUDE = ['nextjs-ecommerce-oneclick', 'monorepo-folders', 'production', 'hello-world-js'];
const ESLINTRC_EXCLUDE = ['nextjs-ecommerce-oneclick', 'monorepo-folders', 'fetch-esm', 'hello-world-js'];
const ESLINTIGNORE_EXCLUDE = ['production', 'hello-world-js'];
const GITIGNORE_EXCLUDE = [
'nextjs-ecommerce-oneclick',
'monorepo-folders',
'production',
'hello-world-js',
'protobufs',
];
const ESLINTRC_EXCLUDE = ['nextjs-ecommerce-oneclick', 'monorepo-folders', 'fetch-esm', 'hello-world-js', 'protobufs'];
const ESLINTIGNORE_EXCLUDE = ['production', 'hello-world-js', 'protobufs'];

const POST_CREATE_EXCLUDE = [
'timer-examples',
Expand All @@ -28,7 +34,7 @@ $.verbose = false;

let [answer] = await question(
`Running pre-commit hook.
This will overwrite any changes made to most config files in samples (like ${chalk.bold('hello-world/tsconfig.json')}).
This will overwrite changes made to most config files in samples (like ${chalk.bold('hello-world/tsconfig.json')}).
Proceed? [Y/n] `
);

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Each directory in this repo is a sample Temporal project built with the [TypeScr
- [**Patching**](https://docs.temporal.io/docs/typescript/patching/): Patch in new Workflow code when making updates to Workflows that have executions in progress in production.
- [**Logging**](https://github.com/temporalio/samples-typescript/tree/main/logging-sinks): Use Sinks to extract data out of Workflows for logging/metrics/tracing purposes.
- [**Instrumentation**](https://github.com/temporalio/samples-typescript/tree/main/instrumentation): Use a [winston](https://github.com/winstonjs/winston) logger to get logs out of all SDK components and get metrics and traces out of Rust Core.
- [**Protobufs**](https://github.com/temporalio/samples-typescript/tree/main/protobufs): Use [Protobufs](https://docs.temporal.io/docs/typescript/data-converters#protobufs).
- [**Custom Payload Converter**](https://github.com/temporalio/samples-typescript/tree/main/ejson): Customize data serialization by creating a `PayloadConverter` that uses EJSON to convert Dates, binary, and regexes.

#### Advanced APIs
Expand Down
4 changes: 3 additions & 1 deletion protobufs/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules
lib
.eslintrc.js
.eslintrc.js
protos

55 changes: 30 additions & 25 deletions protobufs/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
},
plugins: ['@typescript-eslint', 'deprecation'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
rules: {
// recommended for safety
'@typescript-eslint/no-floating-promises': 'error', // forgetting to await Activities and Workflow APIs is bad
'deprecation/deprecation': 'warn',
overrides: [
{
files: ['*.ts'],
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
rules: {
// recommended for safety
'@typescript-eslint/no-floating-promises': 'error', // forgetting to await Activities and Workflow APIs is bad
'deprecation/deprecation': 'warn',

// code style preference
'object-shorthand': ['error', 'always'],
// code style preference
'object-shorthand': ['error', 'always'],

// relaxed rules, for convenience
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
// relaxed rules, for convenience
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-explicit-any': 'off',
},
},
],
'@typescript-eslint/no-explicit-any': 'off',
},
},
],
};
5 changes: 4 additions & 1 deletion protobufs/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
lib
node_modules
node_modules
protos/json-module.js
protos/root.d.ts

2 changes: 2 additions & 0 deletions protobufs/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
protos/json-module.js
protos/root.d.ts
28 changes: 28 additions & 0 deletions protobufs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Protobufs

Use [Protobufs](https://docs.temporal.io/docs/typescript/data-converters#protobufs).

- Example proto files:
- [protos/messages.proto](protos/messages.proto)
- [protos/namespaced-messages.proto](protos/namespaced-messages.proto)
- Scripts for compiling protos: [package.json](package.json)
- Root file: [protos/root.js](protos/root.js)
- Payload Converter: [src/payload-converter.ts](src/payload-converter.ts)

We provide the Payload Converter to the Client ([src/client.ts](src/client.ts)) and Worker ([src/worker.ts](src/worker.ts)), and then we can use Protobufs in the Client, Workflow ([src/workflows.ts](src/workflows.ts)), and Activity ([src/activities.ts](src/activities.ts)).

### Running this sample

1. Make sure Temporal Server is running locally (see the [quick install guide](https://docs.temporal.io/docs/server/quick-install/)).
1. `npm install` to install dependencies.
1. `npm run start.watch` to start the Worker.
1. In another shell, `npm run workflow` to run the Workflow Client.

The client should log the Workflow ID that is started, and you should see it reflected in Temporal Web UI.

Optionally, you can also uncomment the `await handle.result()`, rerun, and see the client script return:

```bash
Started workflow my-business-id-b6155489-920f-41a8-9e88-c17c24d47ee9
{ sentence: 'Proto is 2 years old.' }
```
45 changes: 45 additions & 0 deletions protobufs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "temporal-protobufs",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "ts-node src/worker.ts",
"start.watch": "nodemon src/worker.ts",
"workflow": "ts-node src/client.ts",
"build": "npm-run-all build:protos build:ts",
"build.watch": "npm-run-all build:protos build:ts-watch",
"build:ts": "tsc --build",
"build:ts-watch": "tsc --build --watch",
"build:protos": "pbjs -t json-module -w commonjs -r protobuf-sample -o protos/json-module.js protos/*.proto & pbjs -t static-module protos/*.proto | pbts -o protos/root.d.ts -",
"lint": "eslint ."
},
"nodemonConfig": {
"execMap": {
"ts": "ts-node"
},
"ext": "ts",
"watch": [
"src"
]
},
"dependencies": {
"temporalio": "0.19.x",
"uuid": "^8.3.2"
},
"devDependencies": {
"@tsconfig/node16": "^1.0.0",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-deprecation": "^1.2.1",
"installing": "^1.0.0",
"jsdoc": "^3.6.10",
"nodemon": "^2.0.12",
"npm-run-all": "^4.1.5",
"protobufjs": "^6.11.2",
"ts-node": "^10.2.1",
"typescript": "^4.4.2"
}
}
9 changes: 9 additions & 0 deletions protobufs/protos/messages.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

message ProtoResult {
string sentence = 1;
}

message BinaryMessage {
bytes data = 1;
}
8 changes: 8 additions & 0 deletions protobufs/protos/namespaced-messages.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
syntax = "proto3";

package foo.bar;

message ProtoInput {
string name = 1;
int32 age = 2;
}
8 changes: 8 additions & 0 deletions protobufs/protos/root.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// json-module.js is generated with:
// pbjs -t json-module -w commonjs -o json-module.js protos/*.proto

// @@@SNIPSTART typescript-protobuf-root
const { patchProtobufRoot } = require('@temporalio/common/lib/converter/patch-protobuf-root');
const unpatchedRoot = require('./json-module');
module.exports = patchProtobufRoot(unpatchedRoot);
// @@@SNIPEND
7 changes: 7 additions & 0 deletions protobufs/src/activities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @@@SNIPSTART typescript-protobuf-activity
import { foo, ProtoResult } from '../protos/root';

export async function protoActivity(input: foo.bar.ProtoInput): Promise<ProtoResult> {
return ProtoResult.create({ sentence: `${input.name} is ${input.age} years old.` });
}
// @@@SNIPEND
30 changes: 30 additions & 0 deletions protobufs/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// @@@SNIPSTART typescript-protobuf-client
import { Connection, WorkflowClient } from '@temporalio/client';
import { v4 as uuid } from 'uuid';
import { foo, ProtoResult } from '../protos/root';
import { example } from './workflows';

async function run() {
const client = new WorkflowClient(new Connection().service, {
dataConverter: { payloadConverterPath: require.resolve('./payload-converter') },
});

const handle = await client.start(example, {
args: [foo.bar.ProtoInput.create({ name: 'Proto', age: 2 })],
// can't do:
// args: [new foo.bar.ProtoInput({ name: 'Proto', age: 2 })],
taskQueue: 'protobufs',
workflowId: 'my-business-id-' + uuid(),
});

console.log(`Started workflow ${handle.workflowId}`);

const result: ProtoResult = await handle.result();
console.log(result.toJSON());
}
// @@@SNIPEND

run().catch((err) => {
console.error(err);
process.exit(1);
});
6 changes: 6 additions & 0 deletions protobufs/src/payload-converter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @@@SNIPSTART typescript-protobuf-converter
import { DefaultPayloadConverterWithProtobufs } from '@temporalio/common/lib/protobufs';
import root from '../protos/root';

export const payloadConverter = new DefaultPayloadConverterWithProtobufs({ protobufRoot: root });
// @@@SNIPEND
20 changes: 20 additions & 0 deletions protobufs/src/worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Worker } from '@temporalio/worker';
import * as activities from './activities';

async function run() {
// @@@SNIPSTART typescript-protobuf-worker
const worker = await Worker.create({
workflowsPath: require.resolve('./workflows'),
activities,
taskQueue: 'protobufs',
dataConverter: { payloadConverterPath: require.resolve('./payload-converter') },
});
// @@@SNIPEND

await worker.run();
}

run().catch((err) => {
console.error(err);
process.exit(1);
});
14 changes: 14 additions & 0 deletions protobufs/src/workflows.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @@@SNIPSTART typescript-protobuf-workflow
import { proxyActivities } from '@temporalio/workflow';
import { foo, ProtoResult } from '../protos/root';
import type * as activities from './activities';

const { protoActivity } = proxyActivities<typeof activities>({
startToCloseTimeout: '1 minute',
});

export async function example(input: foo.bar.ProtoInput): Promise<ProtoResult> {
const result = await protoActivity(input);
return result;
}
// @@@SNIPEND

0 comments on commit 819b86a

Please sign in to comment.