video-sync.prisma 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. enum EntityType {
  2. VIDEO
  3. }
  4. enum ChangeType {
  5. CREATED // type = 0
  6. UPDATED // type = 1
  7. DELETED // type = 2
  8. }
  9. model SyncState {
  10. id String @id @default(auto()) @map("_id") @db.ObjectId
  11. entity EntityType
  12. referId String?
  13. lastRunAt DateTime?
  14. lastFullSyncAt DateTime?
  15. createdAt Int
  16. updatedAt Int
  17. @@unique([entity])
  18. @@map("syncState")
  19. }
  20. model SyncChangeNotification {
  21. id String @id @default(auto()) @map("_id") @db.ObjectId
  22. entity EntityType
  23. changeType Int
  24. externalId String?
  25. nonce String?
  26. timestamp BigInt?
  27. sign String?
  28. processed Boolean @default(false)
  29. processedAt DateTime?
  30. statusCode Int?
  31. errorMsg String?
  32. rawBody Json?
  33. createdAt Int
  34. // NEW: explicit notify discriminator (1=new order, 2=status update)
  35. notifyType Int?
  36. // NEW: free-form notes / debug info
  37. notes String?
  38. @@index([entity, externalId])
  39. @@map("syncChangeNotification")
  40. }
  41. model SyncRequestSignature {
  42. id String @id @default(auto()) @map("_id") @db.ObjectId
  43. nonce String @unique
  44. timestamp BigInt
  45. sign String
  46. endpoint String
  47. createdAt Int
  48. @@map("syncRequestSignature")
  49. }
  50. enum SyncRunType {
  51. FULL
  52. NOTIFY
  53. RETRY
  54. }
  55. enum SyncAction {
  56. CREATED
  57. UPDATED
  58. DELETED
  59. NOOP // fetched but nothing changed
  60. FAILED
  61. }
  62. model SyncRun {
  63. id String @id @default(auto()) @map("_id") @db.ObjectId
  64. entity EntityType
  65. type SyncRunType
  66. isInitial Boolean @default(false)
  67. referIdStart String?
  68. referIdEnd String?
  69. pageSize Int?
  70. processedCount Int @default(0)
  71. createdCount Int @default(0)
  72. updatedCount Int @default(0)
  73. deletedCount Int @default(0)
  74. failedCount Int @default(0)
  75. startedAt DateTime
  76. finishedAt DateTime?
  77. status Int? // 0 success, non-zero error code
  78. errorMsg String?
  79. notes String? // NEW: free-form reason/context
  80. createdAt Int
  81. updatedAt Int
  82. records SyncRecord[] @relation("RunToRecords")
  83. @@index([entity, type, startedAt])
  84. @@map("syncRun")
  85. }
  86. model SyncRecord {
  87. id String @id @default(auto()) @map("_id") @db.ObjectId
  88. runId String
  89. run SyncRun @relation("RunToRecords", fields: [runId], references: [id])
  90. entity EntityType
  91. externalId String
  92. action SyncAction
  93. source SyncRunType
  94. processedAt DateTime? // CHANGED: allow pending records
  95. notificationId String?
  96. // Snapshots / Audit
  97. before Json?
  98. after Json?
  99. diff Json?
  100. checksumBefore String?
  101. checksumAfter String?
  102. // NEW: evidence & normalization
  103. payloadRaw String? // verbatim upstream JSON string
  104. payloadHash String? // sha256(payloadRaw)
  105. normalized Json? // our mapped DTO snapshot
  106. resultHash String? // sha256(normalized)
  107. mediaAudit Json? // { photos: [...], video?: {...} }
  108. hold Boolean @default(false) // legal hold (skip retention)
  109. prevRecordId String? @db.ObjectId // chain to previous record for same externalId
  110. // Status semantics (existing)
  111. status Int? // 0=success, 1=transient_failed(pending retry), 2=permanent_failed
  112. errorMsg String?
  113. createdAt Int
  114. updatedAt Int?
  115. // ---------------- NEW: Job identity & retry scheduling ----------------
  116. /// "SubmitOrder" | "SubmitStatus" (null for older/other record types)
  117. jobType String?
  118. attempt Int @default(0)
  119. maxAttempts Int @default(3)
  120. /// epoch seconds for backoff scheduling
  121. nextRunAt Int?
  122. /// De-dupe key; recommend `${jobType}:${externalId}`
  123. dedupeKey String?
  124. // ---------------- NEW: HTTP request/response audit --------------------
  125. requestUrl String?
  126. requestMethod String? // e.g., "POST"
  127. requestHeaders Json?
  128. requestBody Json?
  129. responseCode Int?
  130. responseBody String?
  131. latencyMs Int?
  132. // ----------- NEW: Idempotency & future auth scaffolding ---------------
  133. idempotencyKey String?
  134. securityNonce String?
  135. securityTs BigInt?
  136. securitySign String?
  137. @@index([entity, externalId, processedAt])
  138. @@index([runId])
  139. @@index([entity, action, processedAt])
  140. @@index([entity, externalId, createdAt]) // quick newest lookups
  141. // NEW: scheduler hot-path index
  142. @@index([status, nextRunAt])
  143. // NEW: safe uniqueness for one active logical job per order per type
  144. // (compound unique is safe with nulls in Mongo—docs missing any field don't collide)
  145. @@unique([entity, externalId, jobType])
  146. @@map("syncRecord")
  147. }