-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
097681e
commit 6ef3d8f
Showing
9 changed files
with
171 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import {DurableEventTypeData} from "./types"; | ||
import {getDurableEventStore} from "./store"; | ||
|
||
export function listDurableEventIds(event: DurableEventTypeData) { | ||
const store = getDurableEventStore(event); | ||
return store.keys(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
export * from "./dispatch"; | ||
export * from "./manager"; | ||
export * from "./manager"; | ||
export * from "./schedule"; | ||
export * from "./virtual"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import type {DurableEventSchedule} from "../data"; | ||
import type {DurablePeriodicSyncManager} from "./manager"; | ||
import {getConfig} from "../config"; | ||
import {getPeriodicSyncTagRegistration} from "./manager"; | ||
import {DAY_MS, HOUR_MS, MINUTE_MS, MONTH_MS} from "../data"; | ||
|
||
export interface PeriodicSyncSchedule { | ||
tag: string; | ||
schedule: DurableEventSchedule | ||
} | ||
|
||
export interface GetPeriodicSyncScheduleFn { | ||
(manager: DurablePeriodicSyncManager): Promise<PeriodicSyncSchedule[]> | ||
} | ||
|
||
export interface PeriodicSyncScheduleConfig { | ||
getPeriodicSyncSchedule?: GetPeriodicSyncScheduleFn; | ||
} | ||
|
||
export async function getPeriodicSyncSchedule(manager?: DurablePeriodicSyncManager) { | ||
if (!manager) { | ||
const { periodicSync } = await import("./manager"); | ||
return getPeriodicSyncSchedule(periodicSync); | ||
} | ||
const config = getConfig(); | ||
const fn: GetPeriodicSyncScheduleFn = config.getPeriodicSyncSchedule ?? getDefaultPeriodicSyncSchedule; | ||
return fn(manager); | ||
} | ||
|
||
function getCronExpressionFromInterval(interval: number) { | ||
if (interval <= MINUTE_MS) { | ||
return "0 * * * *"; | ||
} | ||
if (interval <= HOUR_MS) { | ||
return "0 0 * * *"; | ||
} | ||
if (interval <= DAY_MS) { | ||
return "0 0 0 * *"; | ||
} | ||
return undefined; | ||
} | ||
|
||
export async function getDefaultDurableEventScheduleForPeriodicSyncTag(tag: string): Promise<DurableEventSchedule> { | ||
const { minInterval, createdAt } = await getPeriodicSyncTagRegistration(tag); | ||
if (!minInterval) { | ||
return { | ||
immediate: true | ||
}; | ||
} | ||
if (minInterval <= MONTH_MS) { | ||
const cron = getCronExpressionFromInterval(minInterval); | ||
if (cron) { | ||
return { | ||
cron | ||
} | ||
} | ||
} | ||
const createdAtTime = new Date(createdAt).getTime(); | ||
const timeSince = Date.now() - createdAtTime; | ||
const intervalsSince = Math.floor(timeSince / minInterval); | ||
const nextInterval = intervalsSince + 1; | ||
const nextIntervalTime = createdAtTime + (nextInterval * minInterval); | ||
const nextIntervalAt = new Date(nextIntervalTime).toISOString(); | ||
return { | ||
after: nextIntervalAt | ||
}; | ||
} | ||
|
||
export async function getDefaultPeriodicSyncSchedule(manager: DurablePeriodicSyncManager): Promise<PeriodicSyncSchedule[]> { | ||
const tags = await manager.getTags(); | ||
return await Promise.all( | ||
tags.map( | ||
async (tag): Promise<PeriodicSyncSchedule> => { | ||
return { | ||
tag, | ||
schedule: await getDefaultDurableEventScheduleForPeriodicSyncTag(tag) | ||
} | ||
} | ||
) | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import {virtual} from "../events/virtual/virtual"; | ||
import {listDurableEventIds} from "../data/durable-event/list-durable-event-ids"; | ||
import {DurableEventSchedule, getDurableEvent} from "../data"; | ||
import {isMatchingObjects} from "../is"; | ||
import {getPeriodicSyncSchedule} from "./schedule"; | ||
|
||
export const removePeriodicSyncVirtualFunction = virtual(async function * () { | ||
const schedules = await getPeriodicSyncSchedule(); | ||
const type = "periodicsync" | ||
const existingTags = await listDurableEventIds({ | ||
type | ||
}); | ||
const tags = schedules.map(({ tag }) => tag); | ||
const notMatching = existingTags.filter(tag => !tags.includes(tag)); | ||
const { deleteDispatchEvent } = await import("../events"); | ||
for (const tag of notMatching) { | ||
const existing = await getDurableEvent({ | ||
type, | ||
durableEventId: tag | ||
}); | ||
if (existing) { | ||
await deleteDispatchEvent(existing); | ||
} | ||
} | ||
for (const { tag, schedule } of schedules) { | ||
const dispatch = { | ||
durableEventId: tag, | ||
type, | ||
tag, | ||
schedule | ||
}; | ||
const existing = await getDurableEvent(dispatch) | ||
if (existing) { | ||
if (isMatchingDurableEventSchedule(existing.schedule, dispatch.schedule)) { | ||
continue; | ||
} | ||
// Ensure we delete the old schedule before defining a new one | ||
// This shouldn't happen often if periodicSync is staying the same | ||
await deleteDispatchEvent(existing); | ||
} | ||
yield { | ||
type: "dispatch", | ||
dispatch | ||
}; | ||
} | ||
}) | ||
|
||
export function isMatchingDurableEventSchedule(a: DurableEventSchedule, b: DurableEventSchedule) { | ||
return isMatchingObjects(a, b); | ||
} |