Files
AFFiNE-Mirror/packages/backend/server/src/plugins/calendar/cron.ts
T
DarkSky 0bd8160ed4 feat: init cloud calendar support (#14247)
#### PR Dependency Tree


* **PR #14247** 👈
  * **PR #14248**

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

* **New Features**
* Google Calendar integration (disabled by default): link/unlink
accounts, OAuth flow, webhooks, real-time push, background sync,
workspace calendars with customizable items and date-range event
viewing.
* **GraphQL / Client**
* New queries & mutations for accounts, subscriptions, events,
providers, and workspace calendar management.
* **Localization**
* Added localized error message for calendar provider request failures.
* **Tests**
* Backend tests covering sync, webhook renewal, and error/error-recovery
scenarios.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-12 23:17:43 +08:00

62 lines
1.7 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { Models } from '../../models';
import { CalendarService } from './service';
@Injectable()
export class CalendarCronJobs {
constructor(
private readonly models: Models,
private readonly calendar: CalendarService
) {}
@Cron(CronExpression.EVERY_MINUTE)
async pollAccounts() {
const subscriptions =
await this.models.calendarSubscription.listAllWithAccountForSync();
const accountDueAt = new Map<
string,
{ refreshInterval: number; lastSyncAt: Date | null }
>();
for (const subscription of subscriptions) {
const interval = subscription.account.refreshIntervalMinutes ?? 60;
const lastSyncAt = subscription.lastSyncAt ?? null;
const existing = accountDueAt.get(subscription.accountId);
if (!existing) {
accountDueAt.set(subscription.accountId, {
refreshInterval: interval,
lastSyncAt,
});
continue;
}
const earliest =
existing.lastSyncAt && lastSyncAt
? existing.lastSyncAt < lastSyncAt
? existing.lastSyncAt
: lastSyncAt
: (existing.lastSyncAt ?? lastSyncAt);
accountDueAt.set(subscription.accountId, {
refreshInterval: interval,
lastSyncAt: earliest,
});
}
const now = Date.now();
await Promise.allSettled(
Array.from(accountDueAt.entries()).map(([accountId, info]) => {
if (
!info.lastSyncAt ||
now - info.lastSyncAt.getTime() >= info.refreshInterval * 60 * 1000
) {
return this.calendar.syncAccount(accountId);
}
return Promise.resolve();
})
);
}
}