Skip to content

Commit 1377001

Browse files
committed
feat: add logger system
1 parent 364d1fc commit 1377001

9 files changed

Lines changed: 80 additions & 37 deletions

File tree

packages/verrou/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
"dependencies": {
4242
"@lukeed/ms": "^2.0.2",
4343
"@poppinss/utils": "^6.7.0",
44-
"async-mutex": "^0.4.0"
44+
"async-mutex": "^0.4.0",
45+
"typescript-log": "^2.0.0"
4546
},
4647
"devDependencies": {
4748
"@aws-sdk/client-dynamodb": "^3.484.0",

packages/verrou/src/drivers/dynamodb.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,6 @@ export class DynamoDBStore implements LockStore {
6666
}
6767
}
6868

69-
/**
70-
* Get the current owner of a lock
71-
*/
72-
async #getCurrentOwner(key: string) {
73-
await this.#initialized
74-
const command = new GetItemCommand({
75-
TableName: this.#tableName,
76-
Key: { key: { S: key } },
77-
})
78-
79-
const result = await this.#client.send(command)
80-
return result.Item?.owner?.S
81-
}
82-
8369
/**
8470
* Save a lock
8571
*/

packages/verrou/src/lock.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
import { setTimeout } from 'node:timers/promises'
22

33
import { E_LOCK_TIMEOUT } from './errors.js'
4-
import type {
5-
LockAcquireOptions,
6-
LockFactoryConfig,
7-
LockFactoryOptions,
8-
LockStore,
9-
} from './types/main.js'
4+
import type { LockAcquireOptions, LockFactoryConfig, LockStore } from './types/main.js'
105

116
export class Lock {
12-
#config: LockFactoryConfig
137
#owner: string
148

159
constructor(
1610
protected readonly key: string,
1711
protected readonly lockStore: LockStore,
18-
options: LockFactoryOptions = {},
12+
protected config: LockFactoryConfig,
1913
owner?: string,
2014
protected ttl?: number | null,
2115
) {
22-
this.#config = { retry: { attempts: null, delay: 250, ...options.retry } }
2316
this.#owner = owner ?? this.#generateOwner()
2417
}
2518

@@ -44,7 +37,7 @@ export class Lock {
4437
let attemptsDone = 0
4538
const start = Date.now()
4639
const attemptsMax =
47-
options?.retry?.attempts ?? this.#config.retry.attempts ?? Number.POSITIVE_INFINITY
40+
options?.retry?.attempts ?? this.config.retry.attempts ?? Number.POSITIVE_INFINITY
4841

4942
while (attemptsDone++ < attemptsMax) {
5043
const result = await this.lockStore.save(this.key, this.#owner, this.ttl)
@@ -53,12 +46,14 @@ export class Lock {
5346
if (attemptsDone === attemptsMax) throw new E_LOCK_TIMEOUT()
5447

5548
const elapsed = Date.now() - start
56-
if (this.#config.retry.timeout && elapsed > this.#config.retry.timeout) {
49+
if (this.config.retry.timeout && elapsed > this.config.retry.timeout) {
5750
throw new E_LOCK_TIMEOUT()
5851
}
5952

60-
await setTimeout(this.#config.retry.delay ?? 250)
53+
await setTimeout(this.config.retry.delay ?? 250)
6154
}
55+
56+
this.config.logger.debug({ key: this.key }, 'Lock acquired')
6257
}
6358

6459
/**

packages/verrou/src/lock_factory.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { noopLogger } from 'typescript-log'
2+
13
import { Lock } from './lock.js'
24
import { resolveDuration } from './helpers.js'
35
import type { Duration, LockFactoryConfig, LockFactoryOptions, LockStore } from './types/main.js'
@@ -17,7 +19,10 @@ export class LockFactory {
1719
protected readonly store: LockStore,
1820
options: LockFactoryOptions = {},
1921
) {
20-
this.#config = { retry: { attempts: null, delay: 250, ...options.retry } }
22+
this.#config = {
23+
retry: { attempts: null, delay: 250, ...options.retry },
24+
logger: (options.logger ?? noopLogger()).child({ pkg: 'verrou' }),
25+
}
2126
}
2227

2328
/**

packages/verrou/src/types/main.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Logger } from 'typescript-log'
2+
13
export * from './drivers.js'
24

35
/**
@@ -42,10 +44,12 @@ export interface LockAcquireOptions {
4244

4345
export interface LockFactoryOptions {
4446
retry?: RetryConfig
47+
logger?: Logger
4548
}
4649

4750
export interface LockFactoryConfig {
4851
retry: RetryConfig
52+
logger: Logger
4953
}
5054

5155
export interface LockStore {

packages/verrou/src/verrou.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { noopLogger, type Logger } from 'typescript-log'
2+
13
import { LockFactory } from './lock_factory.js'
24
import type { Duration, StoreFactory } from './types/main.js'
35

@@ -22,9 +24,15 @@ export class Verrou<KnownStores extends Record<string, StoreFactory>> {
2224
*/
2325
#storesCache: Map<keyof KnownStores, LockFactory> = new Map()
2426

25-
constructor(config: { default: keyof KnownStores; stores: KnownStores }) {
27+
/**
28+
* Logger instance
29+
*/
30+
#logger: Logger
31+
32+
constructor(config: { default: keyof KnownStores; stores: KnownStores; logger?: Logger }) {
2633
this.#stores = config.stores
2734
this.#defaultStoreName = config.default
35+
this.#logger = (config.logger ?? noopLogger()).child({ pkg: 'verrou' })
2836
}
2937

3038
/**
@@ -38,7 +46,10 @@ export class Verrou<KnownStores extends Record<string, StoreFactory>> {
3846
return this.#storesCache.get(storeToUse)!
3947
}
4048

41-
const factory = new LockFactory(this.#stores[storeToUse]!.driver.factory())
49+
const factory = new LockFactory(this.#stores[storeToUse]!.driver.factory(), {
50+
logger: this.#logger,
51+
})
52+
4253
this.#storesCache.set(storeToUse, factory)
4354

4455
return factory

packages/verrou/tests/lock.spec.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { test } from '@japa/runner'
2+
import { noopLogger } from 'typescript-log'
23

34
import { Lock } from '../src/lock.js'
45
import { E_LOCK_TIMEOUT } from '../src/errors.js'
@@ -8,7 +9,7 @@ import { NullStore } from '../test_helpers/null_store.js'
89
test.group('Lock', () => {
910
test('acquire', async ({ assert }) => {
1011
const store = new MemoryStore()
11-
const lock = new Lock('foo', store)
12+
const lock = new Lock('foo', store, { retry: {}, logger: noopLogger() })
1213

1314
assert.deepEqual(await lock.isLocked(), false)
1415

@@ -24,7 +25,10 @@ test.group('Lock', () => {
2425
}
2526
}
2627

27-
const lock = new Lock('foo', new FakeStore(), { retry: { attempts: 2, delay: 10 } })
28+
const lock = new Lock('foo', new FakeStore(), {
29+
retry: { attempts: 2, delay: 10 },
30+
logger: noopLogger(),
31+
})
2832

2933
// @ts-ignore
3034
await assert.rejects(() => lock.acquire(), E_LOCK_TIMEOUT.message)
@@ -39,7 +43,7 @@ test.group('Lock', () => {
3943
}
4044
}
4145

42-
const lock = new Lock('foo', new FakeStore(), { retry: { attempts: 5 } })
46+
const lock = new Lock('foo', new FakeStore(), { retry: { attempts: 5 }, logger: noopLogger() })
4347

4448
// @ts-ignore
4549
await assert.rejects(() => lock.acquire(), E_LOCK_TIMEOUT.message)
@@ -54,7 +58,10 @@ test.group('Lock', () => {
5458
}
5559

5660
const start = Date.now()
57-
const lock = new Lock('foo', new FakeStore(), { retry: { attempts: 5, delay: 100 } })
61+
const lock = new Lock('foo', new FakeStore(), {
62+
retry: { attempts: 5, delay: 100 },
63+
logger: noopLogger(),
64+
})
5865

5966
// @ts-ignore
6067
await assert.rejects(() => lock.acquire(), E_LOCK_TIMEOUT.message)
@@ -71,7 +78,10 @@ test.group('Lock', () => {
7178
}
7279

7380
const start = Date.now()
74-
const lock = new Lock('foo', new FakeStore(), { retry: { timeout: 100, delay: 10 } })
81+
const lock = new Lock('foo', new FakeStore(), {
82+
retry: { timeout: 100, delay: 10 },
83+
logger: noopLogger(),
84+
})
7585

7686
// @ts-ignore
7787
await assert.rejects(() => lock.acquire(), E_LOCK_TIMEOUT.message)
@@ -84,7 +94,7 @@ test.group('Lock', () => {
8494
assert.plan(3)
8595

8696
const store = new MemoryStore()
87-
const lock = new Lock('foo', store)
97+
const lock = new Lock('foo', store, { retry: {}, logger: noopLogger() })
8898

8999
assert.deepEqual(await lock.isLocked(), false)
90100

@@ -97,7 +107,7 @@ test.group('Lock', () => {
97107

98108
test('run should return callback result', async ({ assert }) => {
99109
const store = new MemoryStore()
100-
const lock = new Lock('foo', store)
110+
const lock = new Lock('foo', store, { retry: {}, logger: noopLogger() })
101111

102112
const result = await lock.run(async () => 'foo')
103113

packages/verrou/tests/verrou.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,24 @@ test.group('Verrou', () => {
4141
const lock = verrou.createLock('foo')
4242
await lock.acquire()
4343
})
44+
45+
test('assign custom logger', async ({ assert }) => {
46+
const logger = {
47+
loggedMessages: [] as any,
48+
child: () => logger,
49+
log: (level: string, message: any) => logger.loggedMessages.push({ level, message }),
50+
trace: (message: any) => logger.log('trace', message),
51+
debug: (...args: any[]) => logger.log('debug', args),
52+
}
53+
54+
const verrou = new Verrou({
55+
default: 'memory',
56+
logger: logger as any,
57+
stores: { memory: { driver: memoryStore() } },
58+
})
59+
60+
await verrou.createLock('foo').acquire()
61+
62+
assert.isAbove(logger.loggedMessages.length, 0)
63+
})
4464
})

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)