feat: complete cmpp gateway delivery recovery workflows
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
||||
-- Add customer-side downstream delivery persistence and uplink matching fields.
|
||||
|
||||
ALTER TABLE "SmsUplinkMessage"
|
||||
ADD COLUMN "applicationId" TEXT,
|
||||
ADD COLUMN "messageRecordId" TEXT,
|
||||
ADD COLUMN "matchStatus" TEXT NOT NULL DEFAULT 'unmatched',
|
||||
ADD COLUMN "matchReason" TEXT;
|
||||
|
||||
ALTER TABLE "SmsUplinkMessage"
|
||||
ADD CONSTRAINT "SmsUplinkMessage_applicationId_fkey"
|
||||
FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "SmsUplinkMessage"
|
||||
ADD CONSTRAINT "SmsUplinkMessage_messageRecordId_fkey"
|
||||
FOREIGN KEY ("messageRecordId") REFERENCES "SmsMessageRecord"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
CREATE INDEX "SmsUplinkMessage_applicationId_receivedAt_idx" ON "SmsUplinkMessage"("applicationId", "receivedAt");
|
||||
CREATE INDEX "SmsUplinkMessage_messageRecordId_idx" ON "SmsUplinkMessage"("messageRecordId");
|
||||
CREATE INDEX "SmsUplinkMessage_matchStatus_idx" ON "SmsUplinkMessage"("matchStatus");
|
||||
|
||||
CREATE TABLE "CmppDownstreamDelivery" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"applicationId" TEXT NOT NULL,
|
||||
"messageRecordId" TEXT,
|
||||
"messageId" TEXT,
|
||||
"deliveryType" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL DEFAULT 'pending',
|
||||
"payload" JSONB NOT NULL,
|
||||
"retryCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"nextRetryAt" TIMESTAMP(3),
|
||||
"deliveredAt" TIMESTAMP(3),
|
||||
"lastError" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "CmppDownstreamDelivery_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
ALTER TABLE "CmppDownstreamDelivery"
|
||||
ADD CONSTRAINT "CmppDownstreamDelivery_tenantId_fkey"
|
||||
FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "CmppDownstreamDelivery"
|
||||
ADD CONSTRAINT "CmppDownstreamDelivery_applicationId_fkey"
|
||||
FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "CmppDownstreamDelivery"
|
||||
ADD CONSTRAINT "CmppDownstreamDelivery_messageRecordId_fkey"
|
||||
FOREIGN KEY ("messageRecordId") REFERENCES "SmsMessageRecord"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
CREATE INDEX "CmppDownstreamDelivery_tenantId_status_createdAt_idx" ON "CmppDownstreamDelivery"("tenantId", "status", "createdAt");
|
||||
CREATE INDEX "CmppDownstreamDelivery_applicationId_status_createdAt_idx" ON "CmppDownstreamDelivery"("applicationId", "status", "createdAt");
|
||||
CREATE INDEX "CmppDownstreamDelivery_messageId_idx" ON "CmppDownstreamDelivery"("messageId");
|
||||
CREATE INDEX "CmppDownstreamDelivery_messageRecordId_idx" ON "CmppDownstreamDelivery"("messageRecordId");
|
||||
CREATE INDEX "CmppDownstreamDelivery_deliveryType_status_idx" ON "CmppDownstreamDelivery"("deliveryType", "status");
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "SmsApplication"
|
||||
ADD COLUMN "cmppMaxConnections" INTEGER NOT NULL DEFAULT 1,
|
||||
ADD COLUMN "cmppWindowSize" INTEGER NOT NULL DEFAULT 16;
|
||||
@@ -0,0 +1,38 @@
|
||||
CREATE TABLE "GatewaySubmitDeadLetter" (
|
||||
"id" TEXT NOT NULL,
|
||||
"streamMessageId" TEXT NOT NULL,
|
||||
"tenantId" TEXT,
|
||||
"applicationId" TEXT,
|
||||
"channelId" TEXT,
|
||||
"traceId" TEXT,
|
||||
"messageId" TEXT,
|
||||
"submitId" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'pending',
|
||||
"failureCode" TEXT NOT NULL,
|
||||
"failureMessage" TEXT NOT NULL,
|
||||
"attempts" INTEGER NOT NULL DEFAULT 1,
|
||||
"maxAttempts" INTEGER NOT NULL DEFAULT 3,
|
||||
"commandPayload" JSONB,
|
||||
"rawPayload" TEXT,
|
||||
"manualRetryCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"lastRetryStreamId" TEXT,
|
||||
"lastRetriedAt" TIMESTAMP(3),
|
||||
"resolvedAt" TIMESTAMP(3),
|
||||
"resolvedStatus" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "GatewaySubmitDeadLetter_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "GatewaySubmitDeadLetter_streamMessageId_key" ON "GatewaySubmitDeadLetter"("streamMessageId");
|
||||
CREATE INDEX "GatewaySubmitDeadLetter_status_createdAt_idx" ON "GatewaySubmitDeadLetter"("status", "createdAt");
|
||||
CREATE INDEX "GatewaySubmitDeadLetter_tenantId_status_createdAt_idx" ON "GatewaySubmitDeadLetter"("tenantId", "status", "createdAt");
|
||||
CREATE INDEX "GatewaySubmitDeadLetter_applicationId_status_createdAt_idx" ON "GatewaySubmitDeadLetter"("applicationId", "status", "createdAt");
|
||||
CREATE INDEX "GatewaySubmitDeadLetter_channelId_status_createdAt_idx" ON "GatewaySubmitDeadLetter"("channelId", "status", "createdAt");
|
||||
CREATE INDEX "GatewaySubmitDeadLetter_messageId_idx" ON "GatewaySubmitDeadLetter"("messageId");
|
||||
CREATE INDEX "GatewaySubmitDeadLetter_submitId_idx" ON "GatewaySubmitDeadLetter"("submitId");
|
||||
|
||||
ALTER TABLE "GatewaySubmitDeadLetter" ADD CONSTRAINT "GatewaySubmitDeadLetter_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "GatewaySubmitDeadLetter" ADD CONSTRAINT "GatewaySubmitDeadLetter_applicationId_fkey" FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "GatewaySubmitDeadLetter" ADD CONSTRAINT "GatewaySubmitDeadLetter_channelId_fkey" FOREIGN KEY ("channelId") REFERENCES "SmsChannel"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
CREATE TABLE "GatewayDownstreamRecoveryStatus" (
|
||||
"id" TEXT NOT NULL,
|
||||
"account" TEXT NOT NULL,
|
||||
"tenantId" TEXT,
|
||||
"applicationId" TEXT,
|
||||
"gatewayInstanceId" TEXT,
|
||||
"state" TEXT NOT NULL,
|
||||
"lastAttemptAt" TIMESTAMP(3),
|
||||
"lastSuccessAt" TIMESTAMP(3),
|
||||
"lastFailureAt" TIMESTAMP(3),
|
||||
"nextRetryAt" TIMESTAMP(3),
|
||||
"attemptCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"lastError" TEXT,
|
||||
"lastSkipReason" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "GatewayDownstreamRecoveryStatus_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "GatewayDownstreamRecoveryStatus_account_key" ON "GatewayDownstreamRecoveryStatus"("account");
|
||||
CREATE INDEX "GatewayDownstreamRecoveryStatus_tenantId_state_updatedAt_idx" ON "GatewayDownstreamRecoveryStatus"("tenantId", "state", "updatedAt");
|
||||
CREATE INDEX "GatewayDownstreamRecoveryStatus_applicationId_state_updatedAt_idx" ON "GatewayDownstreamRecoveryStatus"("applicationId", "state", "updatedAt");
|
||||
CREATE INDEX "GatewayDownstreamRecoveryStatus_state_updatedAt_idx" ON "GatewayDownstreamRecoveryStatus"("state", "updatedAt");
|
||||
CREATE INDEX "GatewayDownstreamRecoveryStatus_nextRetryAt_idx" ON "GatewayDownstreamRecoveryStatus"("nextRetryAt");
|
||||
|
||||
ALTER TABLE "GatewayDownstreamRecoveryStatus"
|
||||
ADD CONSTRAINT "GatewayDownstreamRecoveryStatus_tenantId_fkey"
|
||||
FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "GatewayDownstreamRecoveryStatus"
|
||||
ADD CONSTRAINT "GatewayDownstreamRecoveryStatus_applicationId_fkey"
|
||||
FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE "GatewayDownstreamRecoveryStatus"
|
||||
ADD COLUMN "failureCategory" TEXT;
|
||||
|
||||
CREATE INDEX "GatewayDownstreamRecoveryStatus_failureCategory_updatedAt_idx"
|
||||
ON "GatewayDownstreamRecoveryStatus"("failureCategory", "updatedAt");
|
||||
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE "GatewayDownstreamRecoveryStatus"
|
||||
ADD COLUMN "lockOwner" TEXT,
|
||||
ADD COLUMN "lockExpiresAt" TIMESTAMP(3);
|
||||
|
||||
CREATE INDEX "GatewayDownstreamRecoveryStatus_lockOwner_lockExpiresAt_idx"
|
||||
ON "GatewayDownstreamRecoveryStatus"("lockOwner", "lockExpiresAt");
|
||||
@@ -0,0 +1,64 @@
|
||||
CREATE TABLE "SmsMessageSegmentAudit" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"batchTaskId" TEXT,
|
||||
"messageRecordId" TEXT NOT NULL,
|
||||
"submitRecordId" TEXT,
|
||||
"channelId" TEXT,
|
||||
"submitId" TEXT NOT NULL,
|
||||
"attempt" INTEGER NOT NULL DEFAULT 0,
|
||||
"segmentTotal" INTEGER NOT NULL DEFAULT 1,
|
||||
"segmentIndex" INTEGER NOT NULL DEFAULT 1,
|
||||
"sequenceId" INTEGER,
|
||||
"gatewayMessageId" TEXT,
|
||||
"submitStatus" TEXT NOT NULL DEFAULT 'queued',
|
||||
"receiptStatus" TEXT,
|
||||
"rawStatus" TEXT,
|
||||
"compensationType" TEXT,
|
||||
"errorCode" TEXT,
|
||||
"errorMessage" TEXT,
|
||||
"submittedAt" TIMESTAMP(3),
|
||||
"deliveredAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "SmsMessageSegmentAudit_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "SmsMessageSegmentAudit_messageRecordId_submitId_segmentIndex_key"
|
||||
ON "SmsMessageSegmentAudit"("messageRecordId", "submitId", "segmentIndex");
|
||||
|
||||
CREATE INDEX "SmsMessageSegmentAudit_tenantId_createdAt_idx"
|
||||
ON "SmsMessageSegmentAudit"("tenantId", "createdAt");
|
||||
|
||||
CREATE INDEX "SmsMessageSegmentAudit_messageRecordId_segmentIndex_idx"
|
||||
ON "SmsMessageSegmentAudit"("messageRecordId", "segmentIndex");
|
||||
|
||||
CREATE INDEX "SmsMessageSegmentAudit_submitRecordId_idx"
|
||||
ON "SmsMessageSegmentAudit"("submitRecordId");
|
||||
|
||||
CREATE INDEX "SmsMessageSegmentAudit_gatewayMessageId_idx"
|
||||
ON "SmsMessageSegmentAudit"("gatewayMessageId");
|
||||
|
||||
CREATE INDEX "SmsMessageSegmentAudit_submitStatus_receiptStatus_idx"
|
||||
ON "SmsMessageSegmentAudit"("submitStatus", "receiptStatus");
|
||||
|
||||
ALTER TABLE "SmsMessageSegmentAudit"
|
||||
ADD CONSTRAINT "SmsMessageSegmentAudit_tenantId_fkey"
|
||||
FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "SmsMessageSegmentAudit"
|
||||
ADD CONSTRAINT "SmsMessageSegmentAudit_batchTaskId_fkey"
|
||||
FOREIGN KEY ("batchTaskId") REFERENCES "SmsBatchTask"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "SmsMessageSegmentAudit"
|
||||
ADD CONSTRAINT "SmsMessageSegmentAudit_messageRecordId_fkey"
|
||||
FOREIGN KEY ("messageRecordId") REFERENCES "SmsMessageRecord"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "SmsMessageSegmentAudit"
|
||||
ADD CONSTRAINT "SmsMessageSegmentAudit_submitRecordId_fkey"
|
||||
FOREIGN KEY ("submitRecordId") REFERENCES "SmsSubmitRecord"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "SmsMessageSegmentAudit"
|
||||
ADD CONSTRAINT "SmsMessageSegmentAudit_channelId_fkey"
|
||||
FOREIGN KEY ("channelId") REFERENCES "SmsChannel"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,45 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "SmsUplinkMatchCandidate" (
|
||||
"id" TEXT NOT NULL,
|
||||
"uplinkMessageId" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"applicationId" TEXT NOT NULL,
|
||||
"messageRecordId" TEXT,
|
||||
"matchSource" TEXT NOT NULL,
|
||||
"confidence" INTEGER NOT NULL DEFAULT 50,
|
||||
"reason" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'pending',
|
||||
"claimedAt" TIMESTAMP(3),
|
||||
"claimedById" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "SmsUplinkMatchCandidate_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "SmsUplinkMatchCandidate_uplinkMessageId_applicationId_messageRecordId_key" ON "SmsUplinkMatchCandidate"("uplinkMessageId", "applicationId", "messageRecordId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "SmsUplinkMatchCandidate_uplinkMessageId_status_idx" ON "SmsUplinkMatchCandidate"("uplinkMessageId", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "SmsUplinkMatchCandidate_tenantId_status_createdAt_idx" ON "SmsUplinkMatchCandidate"("tenantId", "status", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "SmsUplinkMatchCandidate_applicationId_status_createdAt_idx" ON "SmsUplinkMatchCandidate"("applicationId", "status", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "SmsUplinkMatchCandidate_messageRecordId_idx" ON "SmsUplinkMatchCandidate"("messageRecordId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "SmsUplinkMatchCandidate" ADD CONSTRAINT "SmsUplinkMatchCandidate_uplinkMessageId_fkey" FOREIGN KEY ("uplinkMessageId") REFERENCES "SmsUplinkMessage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "SmsUplinkMatchCandidate" ADD CONSTRAINT "SmsUplinkMatchCandidate_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "SmsUplinkMatchCandidate" ADD CONSTRAINT "SmsUplinkMatchCandidate_applicationId_fkey" FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "SmsUplinkMatchCandidate" ADD CONSTRAINT "SmsUplinkMatchCandidate_messageRecordId_fkey" FOREIGN KEY ("messageRecordId") REFERENCES "SmsMessageRecord"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
+201
-12
@@ -36,8 +36,13 @@ model Tenant {
|
||||
smsApiRequests SmsApiRequest[]
|
||||
smsSubmitRecords SmsSubmitRecord[]
|
||||
smsReceiptRecords SmsReceiptRecord[]
|
||||
smsMessageSegmentAudits SmsMessageSegmentAudit[]
|
||||
smsUplinkMessages SmsUplinkMessage[]
|
||||
smsUplinkMatchCandidates SmsUplinkMatchCandidate[]
|
||||
cmppDownstreamDeliveries CmppDownstreamDelivery[]
|
||||
cmppConnectionStates CmppConnectionState[]
|
||||
gatewayDownstreamRecoveryStatuses GatewayDownstreamRecoveryStatus[]
|
||||
gatewaySubmitDeadLetters GatewaySubmitDeadLetter[]
|
||||
}
|
||||
|
||||
model EnterpriseCertification {
|
||||
@@ -338,6 +343,8 @@ model SmsApplication {
|
||||
callbackUrl String?
|
||||
cmppAccount String @unique
|
||||
secretHash String
|
||||
cmppMaxConnections Int @default(1)
|
||||
cmppWindowSize Int @default(16)
|
||||
dailyLimit Int?
|
||||
customerUnitPrice Int @default(0)
|
||||
queuePriority String @default("normal")
|
||||
@@ -354,7 +361,12 @@ model SmsApplication {
|
||||
sendTasks SmsSendTask[]
|
||||
batchTasks SmsBatchTask[]
|
||||
messageRecords SmsMessageRecord[]
|
||||
uplinkMessages SmsUplinkMessage[]
|
||||
uplinkMatchCandidates SmsUplinkMatchCandidate[]
|
||||
downstreamDeliveries CmppDownstreamDelivery[]
|
||||
connectionStates CmppConnectionState[]
|
||||
gatewayDownstreamRecoveryStatuses GatewayDownstreamRecoveryStatus[]
|
||||
gatewaySubmitDeadLetters GatewaySubmitDeadLetter[]
|
||||
|
||||
@@index([tenantId, status])
|
||||
}
|
||||
@@ -496,8 +508,10 @@ model SmsChannel {
|
||||
submitSessions CmppSubmitSession[]
|
||||
submitRecords SmsSubmitRecord[]
|
||||
receiptRecords SmsReceiptRecord[]
|
||||
segmentAudits SmsMessageSegmentAudit[]
|
||||
uplinkMessages SmsUplinkMessage[]
|
||||
connectionStates CmppConnectionState[]
|
||||
gatewaySubmitDeadLetters GatewaySubmitDeadLetter[]
|
||||
|
||||
@@index([status])
|
||||
}
|
||||
@@ -818,6 +832,7 @@ model SmsBatchTask {
|
||||
messages SmsMessageRecord[]
|
||||
submitRecords SmsSubmitRecord[]
|
||||
receiptRecords SmsReceiptRecord[]
|
||||
segmentAudits SmsMessageSegmentAudit[]
|
||||
|
||||
@@index([tenantId, status, createdAt])
|
||||
@@index([status, scheduledAt])
|
||||
@@ -876,6 +891,10 @@ model SmsMessageRecord {
|
||||
channel SmsChannel? @relation(fields: [channelId], references: [id])
|
||||
submitRecords SmsSubmitRecord[]
|
||||
receiptRecords SmsReceiptRecord[]
|
||||
segmentAudits SmsMessageSegmentAudit[]
|
||||
matchedUplinks SmsUplinkMessage[] @relation("SmsUplinkMatchedMessage")
|
||||
uplinkMatchCandidates SmsUplinkMatchCandidate[]
|
||||
downstreamDeliveries CmppDownstreamDelivery[]
|
||||
|
||||
@@index([tenantId, status, queuedAt])
|
||||
@@index([batchTaskId, status])
|
||||
@@ -922,12 +941,51 @@ model SmsSubmitRecord {
|
||||
messageRecord SmsMessageRecord @relation(fields: [messageRecordId], references: [id], onDelete: Cascade)
|
||||
channel SmsChannel @relation(fields: [channelId], references: [id])
|
||||
session CmppSubmitSession? @relation(fields: [sessionId], references: [id])
|
||||
segmentAudits SmsMessageSegmentAudit[]
|
||||
|
||||
@@index([tenantId, createdAt])
|
||||
@@index([messageRecordId])
|
||||
@@index([gatewayMessageId])
|
||||
}
|
||||
|
||||
model SmsMessageSegmentAudit {
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
batchTaskId String?
|
||||
messageRecordId String
|
||||
submitRecordId String?
|
||||
channelId String?
|
||||
submitId String
|
||||
attempt Int @default(0)
|
||||
segmentTotal Int @default(1)
|
||||
segmentIndex Int @default(1)
|
||||
sequenceId Int?
|
||||
gatewayMessageId String?
|
||||
submitStatus String @default("queued")
|
||||
receiptStatus String?
|
||||
rawStatus String?
|
||||
compensationType String?
|
||||
errorCode String?
|
||||
errorMessage String?
|
||||
submittedAt DateTime?
|
||||
deliveredAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
batchTask SmsBatchTask? @relation(fields: [batchTaskId], references: [id])
|
||||
messageRecord SmsMessageRecord @relation(fields: [messageRecordId], references: [id], onDelete: Cascade)
|
||||
submitRecord SmsSubmitRecord? @relation(fields: [submitRecordId], references: [id])
|
||||
channel SmsChannel? @relation(fields: [channelId], references: [id])
|
||||
|
||||
@@unique([messageRecordId, submitId, segmentIndex])
|
||||
@@index([tenantId, createdAt])
|
||||
@@index([messageRecordId, segmentIndex])
|
||||
@@index([submitRecordId])
|
||||
@@index([gatewayMessageId])
|
||||
@@index([submitStatus, receiptStatus])
|
||||
}
|
||||
|
||||
model SmsReceiptRecord {
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
@@ -954,21 +1012,152 @@ model SmsReceiptRecord {
|
||||
}
|
||||
|
||||
model SmsUplinkMessage {
|
||||
id String @id @default(cuid())
|
||||
tenantId String?
|
||||
channelId String
|
||||
messageId String?
|
||||
sequenceId Int?
|
||||
phoneNumber String
|
||||
destId String
|
||||
content String
|
||||
receivedAt DateTime
|
||||
createdAt DateTime @default(now())
|
||||
id String @id @default(cuid())
|
||||
tenantId String?
|
||||
applicationId String?
|
||||
channelId String
|
||||
messageRecordId String?
|
||||
messageId String?
|
||||
sequenceId Int?
|
||||
phoneNumber String
|
||||
destId String
|
||||
content String
|
||||
matchStatus String @default("unmatched")
|
||||
matchReason String?
|
||||
receivedAt DateTime
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id])
|
||||
channel SmsChannel @relation(fields: [channelId], references: [id])
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id])
|
||||
application SmsApplication? @relation(fields: [applicationId], references: [id])
|
||||
messageRecord SmsMessageRecord? @relation("SmsUplinkMatchedMessage", fields: [messageRecordId], references: [id])
|
||||
channel SmsChannel @relation(fields: [channelId], references: [id])
|
||||
matchCandidates SmsUplinkMatchCandidate[]
|
||||
|
||||
@@index([tenantId, createdAt])
|
||||
@@index([applicationId, receivedAt])
|
||||
@@index([channelId, receivedAt])
|
||||
@@index([messageRecordId])
|
||||
@@index([matchStatus])
|
||||
@@index([phoneNumber])
|
||||
}
|
||||
|
||||
model SmsUplinkMatchCandidate {
|
||||
id String @id @default(cuid())
|
||||
uplinkMessageId String
|
||||
tenantId String
|
||||
applicationId String
|
||||
messageRecordId String?
|
||||
matchSource String
|
||||
confidence Int @default(50)
|
||||
reason String?
|
||||
status String @default("pending")
|
||||
claimedAt DateTime?
|
||||
claimedById String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
uplinkMessage SmsUplinkMessage @relation(fields: [uplinkMessageId], references: [id], onDelete: Cascade)
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
application SmsApplication @relation(fields: [applicationId], references: [id])
|
||||
messageRecord SmsMessageRecord? @relation(fields: [messageRecordId], references: [id])
|
||||
|
||||
@@unique([uplinkMessageId, applicationId, messageRecordId])
|
||||
@@index([uplinkMessageId, status])
|
||||
@@index([tenantId, status, createdAt])
|
||||
@@index([applicationId, status, createdAt])
|
||||
@@index([messageRecordId])
|
||||
}
|
||||
|
||||
model CmppDownstreamDelivery {
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
applicationId String
|
||||
messageRecordId String?
|
||||
messageId String?
|
||||
deliveryType String
|
||||
status String @default("pending")
|
||||
payload Json
|
||||
retryCount Int @default(0)
|
||||
nextRetryAt DateTime?
|
||||
deliveredAt DateTime?
|
||||
lastError String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
application SmsApplication @relation(fields: [applicationId], references: [id])
|
||||
messageRecord SmsMessageRecord? @relation(fields: [messageRecordId], references: [id])
|
||||
|
||||
@@index([tenantId, status, createdAt])
|
||||
@@index([applicationId, status, createdAt])
|
||||
@@index([messageId])
|
||||
@@index([messageRecordId])
|
||||
@@index([deliveryType, status])
|
||||
}
|
||||
|
||||
model GatewaySubmitDeadLetter {
|
||||
id String @id @default(cuid())
|
||||
streamMessageId String @unique
|
||||
tenantId String?
|
||||
applicationId String?
|
||||
channelId String?
|
||||
traceId String?
|
||||
messageId String?
|
||||
submitId String?
|
||||
status String @default("pending")
|
||||
failureCode String
|
||||
failureMessage String
|
||||
attempts Int @default(1)
|
||||
maxAttempts Int @default(3)
|
||||
commandPayload Json?
|
||||
rawPayload String?
|
||||
manualRetryCount Int @default(0)
|
||||
lastRetryStreamId String?
|
||||
lastRetriedAt DateTime?
|
||||
resolvedAt DateTime?
|
||||
resolvedStatus String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id])
|
||||
application SmsApplication? @relation(fields: [applicationId], references: [id])
|
||||
channel SmsChannel? @relation(fields: [channelId], references: [id])
|
||||
|
||||
@@index([status, createdAt])
|
||||
@@index([tenantId, status, createdAt])
|
||||
@@index([applicationId, status, createdAt])
|
||||
@@index([channelId, status, createdAt])
|
||||
@@index([messageId])
|
||||
@@index([submitId])
|
||||
}
|
||||
|
||||
model GatewayDownstreamRecoveryStatus {
|
||||
id String @id @default(cuid())
|
||||
account String @unique
|
||||
tenantId String?
|
||||
applicationId String?
|
||||
gatewayInstanceId String?
|
||||
state String
|
||||
lockOwner String?
|
||||
lockExpiresAt DateTime?
|
||||
lastAttemptAt DateTime?
|
||||
lastSuccessAt DateTime?
|
||||
lastFailureAt DateTime?
|
||||
nextRetryAt DateTime?
|
||||
attemptCount Int @default(0)
|
||||
failureCategory String?
|
||||
lastError String?
|
||||
lastSkipReason String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id])
|
||||
application SmsApplication? @relation(fields: [applicationId], references: [id])
|
||||
|
||||
@@index([tenantId, state, updatedAt])
|
||||
@@index([applicationId, state, updatedAt])
|
||||
@@index([failureCategory, updatedAt])
|
||||
@@index([lockOwner, lockExpiresAt])
|
||||
@@index([state, updatedAt])
|
||||
@@index([nextRetryAt])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user