Files
AFFiNE-Mirror/packages/backend/server/src/plugins/indexer/event.ts
T
DarkSky 0da32d61ae fix(server): race condition for sync (#14770)
#### PR Dependency Tree


* **PR #14770** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Implemented batch processing for calendar synchronization to improve
performance and resource utilization.
* Added distributed locking to prevent concurrent operations in
multi-instance environments.

* **Bug Fixes**
* Improved reliability by preventing duplicate synchronization attempts.

* **Tests**
  * Enhanced test coverage for batch processing and locking mechanisms.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-03 03:37:09 +08:00

86 lines
1.8 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { Config, JobQueue, OnEvent } from '../../base';
@Injectable()
export class IndexerEvent {
constructor(
private readonly queue: JobQueue,
private readonly config: Config
) {}
@OnEvent('doc.updated')
async indexDoc({ workspaceId, docId }: Events['doc.updated']) {
if (!this.config.indexer.enabled) {
return;
}
await this.queue.add(
'indexer.indexDoc',
{
workspaceId,
docId,
},
{
jobId: `indexDoc/${workspaceId}/${docId}`,
priority: 100,
}
);
}
@OnEvent('doc.snapshot.updated')
async indexWorkspace({ workspaceId, docId }: Events['doc.snapshot.updated']) {
if (!this.config.indexer.enabled) {
return;
}
if (workspaceId !== docId) {
return;
}
await this.queue.add(
'indexer.indexWorkspace',
{ workspaceId },
{ jobId: `indexWorkspace/${workspaceId}`, priority: 100 }
);
}
@OnEvent('user.deleted')
async deleteUserWorkspaces(payload: Events['user.deleted']) {
if (!this.config.indexer.enabled) {
return;
}
for (const workspace of payload.ownedWorkspaces) {
await this.queue.add(
'indexer.deleteWorkspace',
{
workspaceId: workspace,
},
{
jobId: `deleteWorkspace/${workspace}`,
priority: 0,
}
);
}
}
@Cron(CronExpression.EVERY_30_SECONDS)
async autoIndexWorkspaces() {
if (!this.config.indexer.enabled) {
return;
}
await this.queue.add(
'indexer.autoIndexWorkspaces',
{},
{
// make sure only one job is running at a time
delay: 30 * 1000,
jobId: 'autoIndexWorkspaces',
}
);
}
}