mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 00:02:56 +00:00
* refactor(cloud): share PostgreSQL schema startup between services * feat(cloud): add durable native push notification gateway * infra(push): define dedicated gateway resources and operational checks * fix(push): bound cross-host admission and simplify gateway configuration * fix(push): validate deploy configuration and preserve topic-error registrations
53 lines
1.9 KiB
TypeScript
53 lines
1.9 KiB
TypeScript
import type { ApnsClient } from './apns-client.js'
|
|
import type { PushDeviceRegistryStore } from './device-registry-store.js'
|
|
import type { FcmClient } from './fcm-client.js'
|
|
import { fingerprintLogPrefix } from './host-fingerprint.js'
|
|
import type { PushDelivery } from './push-delivery-message.js'
|
|
import type { PushProviderOutcome } from './push-provider-outcome.js'
|
|
|
|
export type PushDispatcherOptions = {
|
|
devices: PushDeviceRegistryStore
|
|
apns?: ApnsClient
|
|
fcm?: FcmClient
|
|
onOutcome?: (outcome: PushProviderOutcome['status']) => void
|
|
}
|
|
|
|
// Retires the registration when the provider says the token is gone.
|
|
export class PushDispatcher {
|
|
constructor(private readonly options: PushDispatcherOptions) {}
|
|
|
|
async sendOnce(delivery: PushDelivery): Promise<PushProviderOutcome> {
|
|
const device = await this.options.devices.findById(delivery.registrationId)
|
|
if (!device || device.dead) return { status: 'dead', reason: 'registration_unavailable' }
|
|
let outcome: PushProviderOutcome
|
|
if (device.platform === 'ios') {
|
|
outcome = this.options.apns
|
|
? await this.options.apns.send(delivery, {
|
|
token: device.token,
|
|
apnsEnvironment: device.apnsEnvironment ?? 'production'
|
|
})
|
|
: { status: 'error', reason: 'apns_not_configured' }
|
|
} else {
|
|
outcome = this.options.fcm
|
|
? await this.options.fcm.send(delivery, { token: device.token })
|
|
: { status: 'error', reason: 'fcm_not_configured' }
|
|
}
|
|
this.options.onOutcome?.(outcome.status)
|
|
if (outcome.status === 'dead') {
|
|
await this.options.devices.markDead(device)
|
|
}
|
|
if (outcome.status !== 'sent') {
|
|
console.warn(
|
|
JSON.stringify({
|
|
event: 'orca_push_delivery_failed',
|
|
platform: device.platform,
|
|
status: outcome.status,
|
|
reason: outcome.reason,
|
|
host: fingerprintLogPrefix(delivery.hostFingerprint)
|
|
})
|
|
)
|
|
}
|
|
return outcome
|
|
}
|
|
}
|