Skip to content

Commit

Permalink
Update NestJS sample (#393)
Browse files Browse the repository at this point in the history
  • Loading branch information
MBach authored Dec 3, 2024
1 parent a07b78a commit 84b5237
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 55 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ jobs:
nestjs-exchange-rates,
timer-examples
]
exclude:
- node: 16
project: nestjs-exchange-rates

steps:
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions nestjs-exchange-rates/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NODE_ENV=<dev|production>
4 changes: 4 additions & 0 deletions nestjs-exchange-rates/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/dist
/node_modules
.env

# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
Expand Down
27 changes: 23 additions & 4 deletions nestjs-exchange-rates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,31 @@ This sample app is based on this [blog post about caching API requests with long
## Installation

```bash
$ npm install
npm install
```

Create an `.env` file from the `.env.template` and chose `dev` or `production`.

- `dev` must be used for testing purposes only
- `production` must be used for production in order to have compiled workflows

Note: you can't start your worker with `npm run start:worker` in production mode.

## Running the app

1. `temporal server start-dev` to start [Temporal Server](https://github.com/temporalio/cli/#installation).
1. `npm run worker` to start the Worker.
1. `npm run start` to start the NestJS server.
1. Visit `http://localhost:3000/exchange-rates/AUD` to see the most recent exchange rate for AUD (Australian Dollar)
2. `npm run start:worker` to start the Worker.
3. `npm run start:server` to start the NestJS server.
4. Visit `http://localhost:3000/exchange-rates/AUD` to see the most recent exchange rate for AUD (Australian Dollar)

## Building the app

For production optimized builds, webpack is used to squash the files into a big `main.js` under the folders `dist/apps/server/` and `dist/apps/worker/`

1. `npm run build:server:prod`
2. `npm run build:worker:prod`

You can locally test your builds before deploying to another server or to the cloud with:

1. `npm run start:server:prod`
2. `npm run start:worker:prod`
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { Client, WorkflowExecutionAlreadyStartedError, Connection, ConnectionOptions } from '@temporalio/client';
import { Provider } from '@nestjs/common';
import {
Client,
WorkflowExecutionAlreadyStartedError,
Connection,
ConnectionOptions,
Workflow,
WorkflowHandle,
} from '@temporalio/client';
import { taskQueue } from '@app/shared';

export const exchangeRatesProviders = [
export const exchangeRatesProviders: Provider[] = [
{
provide: 'CONNECTION_CONFIG',
useValue: {
Expand All @@ -26,7 +34,7 @@ export const exchangeRatesProviders = [
{
provide: 'EXCHANGE_RATES_WORKFLOW_HANDLE',
useFactory: async (client: Client) => {
let handle;
let handle: WorkflowHandle<Workflow>;
try {
handle = await client.workflow.start('exchangeRatesWorkflow', {
taskQueue,
Expand All @@ -36,7 +44,7 @@ export const exchangeRatesProviders = [
} catch (err) {
if (err instanceof WorkflowExecutionAlreadyStartedError) {
console.log('Reusing existing exchange rates workflow');
handle = await client.workflow.getHandle('exchange-rates');
handle = client.workflow.getHandle('exchange-rates');
} else {
throw err;
}
Expand Down
21 changes: 21 additions & 0 deletions nestjs-exchange-rates/apps/worker/scripts/build-workflow-bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { bundleWorkflowCode } from '@temporalio/worker';
import { readFile, writeFile } from 'fs/promises';
import * as path from 'path';

async function bundle() {
const { code } = await bundleWorkflowCode({
workflowsPath: require.resolve('../src/temporal/workflows'),
});
const tsconfigPath = path.join(__dirname, '../tsconfig.app.json');
const tsconfigData = await readFile(tsconfigPath, 'utf-8');
const tsconfig = JSON.parse(tsconfigData);
const codePath = path.join(__dirname, `../${tsconfig.compilerOptions.outDir}/workflow-bundle.js`);

await writeFile(codePath, code);
console.log(`Bundle written to ${codePath}`);
}

bundle().catch((err) => {
console.error(err);
process.exit(0);
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { ActivitiesModule } from '../activities/activities.module';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ActivitiesModule } from '../activities/activities.module';
import { exchangeRatesWorkerProviders } from './exchange-rates-worker.providers';
import { ExchangeRatesWorkerService } from './exchange-rates-worker.service';

@Module({
imports: [ActivitiesModule],
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: true,
}),
ActivitiesModule,
],
controllers: [],
providers: [...exchangeRatesWorkerProviders, ExchangeRatesWorkerService],
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { ConfigService } from '@nestjs/config';
import { ActivitiesService } from '../activities/activities.service';
import { Worker } from '@temporalio/worker';
import { taskQueue } from '@app/shared';

export const exchangeRatesWorkerProviders = [
{
provide: 'EXCHANGE_RATES_WORKER',
inject: [ActivitiesService],
useFactory: async (activitiesService: ActivitiesService) => {
inject: [ActivitiesService, ConfigService],
useFactory: async (activitiesService: ActivitiesService, configService: ConfigService) => {
const activities = {
getExchangeRates: activitiesService.getExchangeRates.bind(activitiesService),
};

const workflowOption =
configService.get<string>('NODE_ENV') === 'production'
? {
workflowBundle: {
codePath: `${__dirname}/workflow-bundle.js`,
},
}
: { workflowsPath: require.resolve('../temporal/workflows') };

const worker = await Worker.create({
workflowsPath: require.resolve('../temporal/workflows'),
taskQueue,
...workflowOption,
activities,
});

Expand Down
3 changes: 2 additions & 1 deletion nestjs-exchange-rates/nest-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"monorepo": true,
"root": "apps/server",
"compilerOptions": {
"deleteOutDir": true,
"webpack": false,
"tsConfigPath": "apps/server/tsconfig.app.json"
},
Expand Down Expand Up @@ -37,4 +38,4 @@
}
}
}
}
}
87 changes: 46 additions & 41 deletions nestjs-exchange-rates/package.json
Original file line number Diff line number Diff line change
@@ -1,59 +1,64 @@
{
"name": "nest-typescript-starter",
"name": "nestjs-typescript-starter",
"private": true,
"version": "1.0.0",
"description": "Nest TypeScript starter repository",
"version": "2.0.0",
"description": "NestJS TypeScript starter repository",
"license": "MIT",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"build": "npm run build:server && npm run build:worker",
"build:server": "nest build --webpack server",
"build:worker": "nest build --webpack worker && ts-node apps/worker/scripts/build-workflow-bundle.ts",
"format": "prettier --write \"apps/**/*.ts\" \"libs/**/*.ts\"",
"start": "nest start server",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"start:server": "nest start server",
"start:server:dev": "nest start --watch",
"start:server:debug": "nest start --debug --watch",
"start:server:prod": "node dist/apps/server/main",
"start:worker": "nest start worker",
"start:worker:dev": "nest start worker --watch",
"start:worker:debug": "nest start worker --debug --watch",
"start:worker:prod": "node dist/apps/worker/main",
"test": "jest",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"worker": "nest start worker"
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
},
"dependencies": {
"@nestjs/axios": "0.1.0",
"@nestjs/common": "^8.4.7",
"@nestjs/core": "^8.4.7",
"@nestjs/platform-express": "^8.4.7",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"@nestjs/axios": "3.1.2",
"@nestjs/common": "^10.4.8",
"@nestjs/config": "^3.3.0",
"@nestjs/core": "^10.4.8",
"@nestjs/platform-express": "^10.4.8",
"axios": "^1.3.1",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.4.0",
"@temporalio/activity": "^1.11.3",
"@temporalio/client": "^1.11.3",
"@temporalio/common": "^1.11.3",
"@temporalio/worker": "^1.11.3",
"@temporalio/workflow": "^1.11.3"
"@temporalio/activity": "^1.11.5",
"@temporalio/client": "^1.11.5",
"@temporalio/common": "^1.11.5",
"@temporalio/worker": "^1.11.5",
"@temporalio/workflow": "^1.11.5"
},
"devDependencies": {
"@nestjs/cli": "^8.1.3",
"@nestjs/schematics": "^8.0.4",
"@nestjs/testing": "^8.1.1",
"@temporalio/testing": "^1.11.3",
"@types/express": "^4.17.13",
"@types/jest": "^27.0.2",
"@types/node": "^16.11.1",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "5.x",
"@typescript-eslint/parser": "5.x",
"eslint": "^7.32.0",
"@nestjs/cli": "^10.4.8",
"@nestjs/schematics": "^10.2.3",
"@nestjs/testing": "^10.4.8",
"@temporalio/testing": "^1.11.5",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.14",
"@types/node": "^20.3.1",
"@types/supertest": "^6.0.2",
"@typescript-eslint/eslint-plugin": "8.15.0",
"@typescript-eslint/parser": "8.15.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^27.3.0",
"nodemon": "^2.0.12",
"jest": "^29.7.0",
"nodemon": "^3.1.7",
"prettier": "^2.8.8",
"source-map-support": "^0.5.20",
"source-map-support": "^0.5.21",
"supertest": "^6.1.6",
"ts-jest": "^27.0.7",
"ts-loader": "^9.2.6",
"ts-node": "^10.3.0",
"tsconfig-paths": "^3.11.0",
"typescript": "^4.4.4"
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.6.3"
},
"jest": {
"moduleFileExtensions": [
Expand Down

0 comments on commit 84b5237

Please sign in to comment.