Skip to content

Commit 26afe8a

Browse files
authored
Merge pull request #119 from resonatehq/main
Release 0.5.3
2 parents d4e506e + c3f1166 commit 26afe8a

11 files changed

+382
-339
lines changed

lib/core/errors.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ export enum ErrorCodes {
1313

1414
// store
1515
STORE = 40,
16-
STORE_PAYLOAD = 41,
17-
STORE_FORBIDDEN = 42,
18-
STORE_NOT_FOUND = 43,
19-
STORE_ALREADY_EXISTS = 44,
20-
STORE_INVALID_STATE = 45,
21-
STORE_ENCODER = 46,
16+
STORE_UNAUTHORIZED = 41,
17+
STORE_PAYLOAD = 42,
18+
STORE_FORBIDDEN = 43,
19+
STORE_NOT_FOUND = 44,
20+
STORE_ALREADY_EXISTS = 45,
21+
STORE_INVALID_STATE = 46,
22+
STORE_ENCODER = 47,
2223
}
2324

2425
export class ResonateError extends Error {

lib/core/options.ts

+57-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,23 @@ import { IStore } from "./store";
77
* Resonate configuration options.
88
*/
99
export type ResonateOptions = {
10+
/**
11+
* Store authentication options.
12+
*/
13+
auth: AuthOptions;
14+
1015
/**
1116
* An encoder instance used for encoding and decoding values
1217
* returned (or thrown) by registered functions. If not provided,
1318
* a default JSON encoder will be used.
1419
*/
1520
encoder: IEncoder<unknown, string | undefined>;
1621

22+
/**
23+
* The frequency in ms to heartbeat locks.
24+
*/
25+
heartbeat: number;
26+
1727
/**
1828
* A process id that can be used to uniquely identify this Resonate
1929
* instance. If not provided a default value will be generated.
@@ -43,8 +53,8 @@ export type ResonateOptions = {
4353
tags: Record<string, string>;
4454

4555
/**
46-
* A store instance, if provided this will take precedence over a
47-
* remote store.
56+
* A store instance, if provided will take predence over the
57+
* default store.
4858
*/
4959
store: IStore;
5060

@@ -124,3 +134,48 @@ export type PartialOptions = Partial<Options> & { __resonate: true };
124134
export function isOptions(o: unknown): o is PartialOptions {
125135
return typeof o === "object" && o !== null && (o as PartialOptions).__resonate === true;
126136
}
137+
138+
export type StoreOptions = {
139+
/**
140+
* The store authentication options.
141+
*/
142+
auth: AuthOptions;
143+
144+
/**
145+
* The store encoder, defaults to a base64 encoder.
146+
*/
147+
encoder: IEncoder<string, string>;
148+
149+
/**
150+
* The frequency in ms to heartbeat locks.
151+
*/
152+
heartbeat: number;
153+
154+
/**
155+
* A logger instance, if not provided a default logger will be
156+
* used.
157+
*/
158+
logger: ILogger;
159+
160+
/**
161+
* A process id that can be used to uniquely identify this Resonate
162+
* instance. If not provided a default value will be generated.
163+
*/
164+
pid: string;
165+
166+
/**
167+
* Number of retries to attempt before throwing an error. If not
168+
* provided, a default value will be used.
169+
*/
170+
retries: number;
171+
};
172+
173+
export type AuthOptions = {
174+
/**
175+
* Basic auth credentials.
176+
*/
177+
basic: {
178+
password: string;
179+
username: string;
180+
};
181+
};

lib/core/promises/promises.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -410,19 +410,23 @@ export class DurablePromise<T> {
410410
await this.poll();
411411

412412
// set timeout promise
413+
let timeoutId: NodeJS.Timeout | undefined;
413414
const timeoutPromise =
414415
timeout === Infinity
415416
? new Promise(() => {}) // wait forever
416-
: new Promise((resolve) => setTimeout(resolve, timeout));
417+
: new Promise((resolve) => (timeoutId = setTimeout(resolve, timeout)));
417418

418419
// await either:
419420
// - completion of the promise
420421
// - timeout
421-
await Promise.any([this.completed, timeoutPromise]);
422+
await Promise.race([this.completed, timeoutPromise]);
422423

423-
// stop polling interval
424+
// clear polling interval
424425
clearInterval(this.interval);
425426

427+
// clear timeout
428+
clearTimeout(timeoutId);
429+
426430
// throw error if timeout occcured
427431
if (this.pending) {
428432
throw new Error("Timeout occured while waiting for promise to complete");

lib/core/stores/local.ts

+17-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as cronParser from "cron-parser";
22
import { ErrorCodes, ResonateError } from "../errors";
33
import { ILogger } from "../logger";
44
import { Logger } from "../loggers/logger";
5+
import { StoreOptions } from "../options";
56
import {
67
DurablePromise,
78
PendingPromise,
@@ -26,18 +27,22 @@ export class LocalStore implements IStore {
2627
public schedules: LocalScheduleStore;
2728
public locks: LocalLockStore;
2829

30+
public readonly logger: ILogger;
31+
2932
private toSchedule: Schedule[] = [];
3033
private next: number | undefined = undefined;
3134

3235
constructor(
33-
private logger: ILogger = new Logger(),
36+
opts: Partial<StoreOptions> = {},
3437
promiseStorage: IStorage<DurablePromise> = new WithTimeout(new MemoryStorage<DurablePromise>()),
3538
scheduleStorage: IStorage<Schedule> = new MemoryStorage<Schedule>(),
3639
lockStorage: IStorage<{ id: string; eid: string }> = new MemoryStorage<{ id: string; eid: string }>(),
3740
) {
38-
this.promises = new LocalPromiseStore(promiseStorage);
39-
this.schedules = new LocalScheduleStore(scheduleStorage, this);
40-
this.locks = new LocalLockStore(lockStorage);
41+
this.promises = new LocalPromiseStore(this, promiseStorage);
42+
this.schedules = new LocalScheduleStore(this, scheduleStorage);
43+
this.locks = new LocalLockStore(this, lockStorage);
44+
45+
this.logger = opts.logger ?? new Logger();
4146

4247
this.init();
4348
}
@@ -115,7 +120,10 @@ export class LocalStore implements IStore {
115120
}
116121

117122
export class LocalPromiseStore implements IPromiseStore {
118-
constructor(private storage: IStorage<DurablePromise> = new MemoryStorage<DurablePromise>()) {}
123+
constructor(
124+
private store: LocalStore,
125+
private storage: IStorage<DurablePromise>,
126+
) {}
119127

120128
async create(
121129
id: string,
@@ -327,8 +335,8 @@ export class LocalPromiseStore implements IPromiseStore {
327335

328336
export class LocalScheduleStore implements IScheduleStore {
329337
constructor(
330-
private storage: IStorage<Schedule> = new MemoryStorage<Schedule>(),
331-
private store: LocalStore | undefined = undefined,
338+
private store: LocalStore,
339+
private storage: IStorage<Schedule>,
332340
) {}
333341

334342
async create(
@@ -456,7 +464,8 @@ export class LocalScheduleStore implements IScheduleStore {
456464

457465
export class LocalLockStore implements ILockStore {
458466
constructor(
459-
private storage: IStorage<{ id: string; eid: string }> = new MemoryStorage<{ id: string; eid: string }>(),
467+
private store: LocalStore,
468+
private storage: IStorage<{ id: string; eid: string }>,
460469
) {}
461470

462471
async tryAcquire(id: string, eid: string): Promise<boolean> {

0 commit comments

Comments
 (0)