mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 17:44:03 +00:00
feat(bot): add self-hosted scheduled dispatch support
Co-authored-by: claw <stanislavkalishin+claw@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { and, asc, eq } from 'drizzle-orm'
|
||||
import { and, asc, eq, lte } from 'drizzle-orm'
|
||||
|
||||
import { createDbClient, schema } from '@household/db'
|
||||
import { instantFromDatabaseValue, instantToDate, nowInstant } from '@household/domain'
|
||||
@@ -129,6 +129,26 @@ export function createDbScheduledDispatchRepository(databaseUrl: string): {
|
||||
return rows.map(mapScheduledDispatch)
|
||||
},
|
||||
|
||||
async listDueScheduledDispatches(input) {
|
||||
const filters = [
|
||||
eq(schema.scheduledDispatches.status, 'scheduled'),
|
||||
lte(schema.scheduledDispatches.dueAt, instantToDate(input.dueBefore))
|
||||
]
|
||||
|
||||
if (input.provider) {
|
||||
filters.push(eq(schema.scheduledDispatches.provider, input.provider))
|
||||
}
|
||||
|
||||
const rows = await db
|
||||
.select(scheduledDispatchSelect())
|
||||
.from(schema.scheduledDispatches)
|
||||
.where(and(...filters))
|
||||
.orderBy(asc(schema.scheduledDispatches.dueAt), asc(schema.scheduledDispatches.createdAt))
|
||||
.limit(input.limit)
|
||||
|
||||
return rows.map(mapScheduledDispatch)
|
||||
},
|
||||
|
||||
async updateScheduledDispatch(input) {
|
||||
const updates: Record<string, unknown> = {
|
||||
updatedAt: instantToDate(input.updatedAt)
|
||||
|
||||
@@ -68,6 +68,19 @@ class ScheduledDispatchRepositoryStub implements ScheduledDispatchRepository {
|
||||
return [...this.dispatches.values()].filter((dispatch) => dispatch.householdId === householdId)
|
||||
}
|
||||
|
||||
async listDueScheduledDispatches(input: {
|
||||
dueBefore: Temporal.Instant
|
||||
provider?: ScheduledDispatchRecord['provider']
|
||||
limit: number
|
||||
}): Promise<readonly ScheduledDispatchRecord[]> {
|
||||
return [...this.dispatches.values()]
|
||||
.filter((dispatch) => dispatch.status === 'scheduled')
|
||||
.filter((dispatch) => dispatch.dueAt.epochMilliseconds <= input.dueBefore.epochMilliseconds)
|
||||
.filter((dispatch) => (input.provider ? dispatch.provider === input.provider : true))
|
||||
.sort((left, right) => left.dueAt.epochMilliseconds - right.dueAt.epochMilliseconds)
|
||||
.slice(0, input.limit)
|
||||
}
|
||||
|
||||
async updateScheduledDispatch(input: {
|
||||
dispatchId: string
|
||||
dueAt?: Temporal.Instant
|
||||
|
||||
@@ -86,6 +86,7 @@ export interface ScheduledDispatchService {
|
||||
cancelAdHocNotification(notificationId: string, cancelledAt?: Instant): Promise<void>
|
||||
reconcileHouseholdBuiltInDispatches(householdId: string, asOf?: Instant): Promise<void>
|
||||
reconcileAllBuiltInDispatches(asOf?: Instant): Promise<void>
|
||||
listDueDispatches(input?: { asOf?: Instant; limit?: number }): Promise<readonly ScheduledDispatchRecord[]>
|
||||
getDispatchById(dispatchId: string): Promise<ScheduledDispatchRecord | null>
|
||||
claimDispatch(dispatchId: string): Promise<boolean>
|
||||
releaseDispatch(dispatchId: string): Promise<void>
|
||||
@@ -307,6 +308,14 @@ export function createScheduledDispatchService(input: {
|
||||
}
|
||||
},
|
||||
|
||||
listDueDispatches(inputValue) {
|
||||
return input.repository.listDueScheduledDispatches({
|
||||
dueBefore: inputValue?.asOf ?? nowInstant(),
|
||||
provider: input.scheduler.provider,
|
||||
limit: inputValue?.limit ?? 25
|
||||
})
|
||||
},
|
||||
|
||||
getDispatchById(dispatchId) {
|
||||
return input.repository.getScheduledDispatchById(dispatchId)
|
||||
},
|
||||
|
||||
@@ -7,7 +7,11 @@ export const SCHEDULED_DISPATCH_KINDS = [
|
||||
'rent_due'
|
||||
] as const
|
||||
export const SCHEDULED_DISPATCH_STATUSES = ['scheduled', 'sent', 'cancelled'] as const
|
||||
export const SCHEDULED_DISPATCH_PROVIDERS = ['gcp-cloud-tasks', 'aws-eventbridge'] as const
|
||||
export const SCHEDULED_DISPATCH_PROVIDERS = [
|
||||
'gcp-cloud-tasks',
|
||||
'aws-eventbridge',
|
||||
'self-hosted'
|
||||
] as const
|
||||
|
||||
export type ScheduledDispatchKind = (typeof SCHEDULED_DISPATCH_KINDS)[number]
|
||||
export type ScheduledDispatchStatus = (typeof SCHEDULED_DISPATCH_STATUSES)[number]
|
||||
@@ -64,6 +68,11 @@ export interface ScheduledDispatchRepository {
|
||||
listScheduledDispatchesForHousehold(
|
||||
householdId: string
|
||||
): Promise<readonly ScheduledDispatchRecord[]>
|
||||
listDueScheduledDispatches(input: {
|
||||
dueBefore: Instant
|
||||
provider?: ScheduledDispatchProvider
|
||||
limit: number
|
||||
}): Promise<readonly ScheduledDispatchRecord[]>
|
||||
updateScheduledDispatch(
|
||||
input: UpdateScheduledDispatchInput
|
||||
): Promise<ScheduledDispatchRecord | null>
|
||||
|
||||
Reference in New Issue
Block a user