nats-jobs
Version:
Background job processor using NATS
62 lines (57 loc) • 1.67 kB
text/typescript
/*
* Demonstrates how to process only one resource at a time
* when multiple clients are pulling from the same consumer.
*
* To Test:
*
* (1) Run two or more instances of the script:
* npx ts-node examples/exclusiveLock.ts
* (2) Publish multiple messages with the same value:
* nats pub ORDERS 10
* nats pub ORDERS 11
* nats pub ORDERS 11
* nats pub ORDERS 10
*
* Requires NATS and Redis to be running.
*/
import { JsMsg, StringCodec } from 'nats'
import Redis from 'ioredis'
import Redlock from 'redlock'
import { setTimeout } from 'node:timers/promises'
import ms from 'ms'
import { jobProcessor } from '../src/jobProcessor'
const sc = StringCodec()
const redis = new Redis()
const redlock = new Redlock([redis])
const def = {
stream: 'ORDERS',
numAttempts: 3,
async perform(msg: JsMsg) {
const id = msg.data.toString()
// Lock resource where a stream that could contain duplicates that
// need to be processed in a serialized manner.
const resources = [`mySite:${id}`]
const lockDuration = ms('10s')
// Attempt to run some code
await redlock.using(resources, lockDuration, async (signal) => {
console.log('LOCK OBTAINED')
const data = sc.decode(msg.data)
for (let i = 0; i < 5; i++) {
// Indicate we're still working
msg.working()
// Simulate some work
await setTimeout(ms('1s'))
console.log(i, data)
// Make sure any attempted lock extension has not failed
if (signal.aborted) {
throw signal.error
}
}
})
},
}
const run = async () => {
const processor = await jobProcessor()
processor.start(def)
}
run()