mirror of
https://github.com/docmost/docmost.git
synced 2026-08-29 18:14:58 +08:00
feat(base): wire formula recompute job into queue processor
This commit is contained in:
@@ -37,4 +37,7 @@ export enum EventName {
|
|||||||
BASE_VIEW_DELETED = 'base.view.deleted',
|
BASE_VIEW_DELETED = 'base.view.deleted',
|
||||||
|
|
||||||
BASE_SCHEMA_BUMPED = 'base.schema.bumped',
|
BASE_SCHEMA_BUMPED = 'base.schema.bumped',
|
||||||
|
BASE_ROWS_UPDATED = 'base.rows.updated',
|
||||||
|
BASE_FORMULA_RECOMPUTE_STARTED = 'base.formula.recompute.started',
|
||||||
|
BASE_FORMULA_RECOMPUTE_COMPLETED = 'base.formula.recompute.completed',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,3 +46,20 @@ export type BaseViewUpdatedEvent = BaseEventBase & { view: BaseView };
|
|||||||
export type BaseViewDeletedEvent = BaseEventBase & { viewId: string };
|
export type BaseViewDeletedEvent = BaseEventBase & { viewId: string };
|
||||||
|
|
||||||
export type BaseSchemaBumpedEvent = BaseEventBase & { schemaVersion: number };
|
export type BaseSchemaBumpedEvent = BaseEventBase & { schemaVersion: number };
|
||||||
|
|
||||||
|
export type BaseRowsUpdatedEvent = BaseEventBase & {
|
||||||
|
rowIds: string[];
|
||||||
|
propertyIds: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BaseFormulaRecomputeStartedEvent = BaseEventBase & {
|
||||||
|
propertyIds: string[];
|
||||||
|
jobId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BaseFormulaRecomputeCompletedEvent = BaseEventBase & {
|
||||||
|
propertyIds: string[];
|
||||||
|
jobId: string;
|
||||||
|
processed: number;
|
||||||
|
errored: number;
|
||||||
|
};
|
||||||
|
|||||||
@@ -11,14 +11,20 @@ import { BaseRepo } from '@docmost/db/repos/base/base.repo';
|
|||||||
import { QueueJob, QueueName } from '../../../integrations/queue/constants';
|
import { QueueJob, QueueName } from '../../../integrations/queue/constants';
|
||||||
import {
|
import {
|
||||||
IBaseCellGcJob,
|
IBaseCellGcJob,
|
||||||
|
IBaseFormulaRecomputeJob,
|
||||||
IBaseTypeConversionJob,
|
IBaseTypeConversionJob,
|
||||||
} from '../../../integrations/queue/constants/queue.interface';
|
} from '../../../integrations/queue/constants/queue.interface';
|
||||||
import { processBaseTypeConversion } from '../tasks/base-type-conversion.task';
|
import { processBaseTypeConversion } from '../tasks/base-type-conversion.task';
|
||||||
import { processBaseCellGc } from '../tasks/base-cell-gc.task';
|
import { processBaseCellGc } from '../tasks/base-cell-gc.task';
|
||||||
|
import { processBaseFormulaRecompute } from '../tasks/base-formula-recompute.task';
|
||||||
|
import { FormulaLockService } from '../formula/formula-lock';
|
||||||
import { EventName } from '../../../common/events/event.contants';
|
import { EventName } from '../../../common/events/event.contants';
|
||||||
import {
|
import {
|
||||||
BasePropertyUpdatedEvent,
|
BasePropertyUpdatedEvent,
|
||||||
BaseSchemaBumpedEvent,
|
BaseSchemaBumpedEvent,
|
||||||
|
BaseFormulaRecomputeStartedEvent,
|
||||||
|
BaseFormulaRecomputeCompletedEvent,
|
||||||
|
BaseRowsUpdatedEvent,
|
||||||
} from '../events/base-events';
|
} from '../events/base-events';
|
||||||
|
|
||||||
@Processor(QueueName.BASE_QUEUE)
|
@Processor(QueueName.BASE_QUEUE)
|
||||||
@@ -34,6 +40,7 @@ export class BaseQueueProcessor
|
|||||||
private readonly basePropertyRepo: BasePropertyRepo,
|
private readonly basePropertyRepo: BasePropertyRepo,
|
||||||
private readonly baseRepo: BaseRepo,
|
private readonly baseRepo: BaseRepo,
|
||||||
private readonly eventEmitter: EventEmitter2,
|
private readonly eventEmitter: EventEmitter2,
|
||||||
|
private readonly formulaLock: FormulaLockService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -104,6 +111,73 @@ export class BaseQueueProcessor
|
|||||||
this.emitSchemaBumped(data.baseId, data.workspaceId, schemaVersion);
|
this.emitSchemaBumped(data.baseId, data.workspaceId, schemaVersion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case QueueJob.BASE_FORMULA_RECOMPUTE: {
|
||||||
|
const data = job.data as IBaseFormulaRecomputeJob;
|
||||||
|
const token = await this.formulaLock.acquireWait(data.baseId, {
|
||||||
|
timeoutMs: 30_000,
|
||||||
|
});
|
||||||
|
if (!token) {
|
||||||
|
throw new Error(
|
||||||
|
`formula recompute: lock acquire timeout for base ${data.baseId}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.eventEmitter.emit(EventName.BASE_FORMULA_RECOMPUTE_STARTED, {
|
||||||
|
baseId: data.baseId,
|
||||||
|
workspaceId: data.workspaceId,
|
||||||
|
actorId: data.actorId ?? null,
|
||||||
|
requestId: null,
|
||||||
|
propertyIds: data.propertyIds,
|
||||||
|
jobId: String(job.id ?? ''),
|
||||||
|
} satisfies BaseFormulaRecomputeStartedEvent);
|
||||||
|
|
||||||
|
const result = await processBaseFormulaRecompute(
|
||||||
|
this.db,
|
||||||
|
this.baseRowRepo,
|
||||||
|
this.basePropertyRepo,
|
||||||
|
data,
|
||||||
|
{
|
||||||
|
progress: (processed) => job.updateProgress({ processed }),
|
||||||
|
onBatch: async (batch) => {
|
||||||
|
this.eventEmitter.emit(EventName.BASE_ROWS_UPDATED, {
|
||||||
|
baseId: data.baseId,
|
||||||
|
workspaceId: data.workspaceId,
|
||||||
|
actorId: null,
|
||||||
|
requestId: null,
|
||||||
|
rowIds: batch.map((b) => b.id),
|
||||||
|
propertyIds: data.propertyIds,
|
||||||
|
} satisfies BaseRowsUpdatedEvent);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const schemaVersion = await this.baseRepo.bumpSchemaVersion(
|
||||||
|
data.baseId,
|
||||||
|
);
|
||||||
|
this.eventEmitter.emit(EventName.BASE_SCHEMA_BUMPED, {
|
||||||
|
baseId: data.baseId,
|
||||||
|
workspaceId: data.workspaceId,
|
||||||
|
actorId: data.actorId ?? null,
|
||||||
|
requestId: null,
|
||||||
|
schemaVersion,
|
||||||
|
} satisfies BaseSchemaBumpedEvent);
|
||||||
|
|
||||||
|
this.eventEmitter.emit(EventName.BASE_FORMULA_RECOMPUTE_COMPLETED, {
|
||||||
|
baseId: data.baseId,
|
||||||
|
workspaceId: data.workspaceId,
|
||||||
|
actorId: data.actorId ?? null,
|
||||||
|
requestId: null,
|
||||||
|
propertyIds: data.propertyIds,
|
||||||
|
jobId: String(job.id ?? ''),
|
||||||
|
processed: result.processed,
|
||||||
|
errored: result.errored,
|
||||||
|
} satisfies BaseFormulaRecomputeCompletedEvent);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
await this.formulaLock.release(data.baseId, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
this.logger.warn(`Unknown job: ${job.name}`);
|
this.logger.warn(`Unknown job: ${job.name}`);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user