feat(ops): 数据保留清理、CORS 白名单与上传失败回滚
- 新增每日数据保留清理任务:按保留期清空原始报文、删除过期 事件/审计记录,批量幂等可重跑;067 迁移补齐清理索引并清理 冗余索引,check-sql-guard 增加防线 - 生产 CORS 改为显式来源白名单(CORS_ALLOWED_ORIGINS),禁用 通配符,非通配响应补充 Vary: Origin - 文件上传任一步失败时回滚已上传对象,清理失败记录 warn 日志 - 新增 HTTP/CORS 与 PostgreSQL 集成测试;若干文件仅 prettier 重排
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
import { Pool } from 'pg'
|
||||
|
||||
const connectionString = process.env.TEST_POSTGRES_URL
|
||||
|
||||
test('real PostgreSQL transaction rolls back atomically', { skip: !connectionString }, async () => {
|
||||
const pool = new Pool({ connectionString })
|
||||
const client = await pool.connect()
|
||||
const tableName = `integration_tx_${Date.now()}`
|
||||
try {
|
||||
await client.query(`CREATE TEMP TABLE ${tableName} (id integer primary key, value text)`)
|
||||
await client.query('BEGIN')
|
||||
await client.query(`INSERT INTO ${tableName} (id, value) VALUES (1, 'before-error')`)
|
||||
try {
|
||||
await client.query(`INSERT INTO ${tableName} (id, value) VALUES (1, 'duplicate')`)
|
||||
} catch {
|
||||
await client.query('ROLLBACK')
|
||||
}
|
||||
const result = await client.query(`SELECT COUNT(*)::int AS count FROM ${tableName}`)
|
||||
assert.equal(result.rows[0].count, 0)
|
||||
} finally {
|
||||
client.release()
|
||||
await pool.end()
|
||||
}
|
||||
})
|
||||
|
||||
test(
|
||||
'real PostgreSQL enforces callback replay idempotency under concurrency',
|
||||
{
|
||||
skip: !connectionString,
|
||||
},
|
||||
async () => {
|
||||
const pool = new Pool({ connectionString })
|
||||
const tableName = `integration_webhook_${Date.now()}`
|
||||
try {
|
||||
await pool.query(
|
||||
`CREATE TEMP TABLE ${tableName} (
|
||||
id serial primary key,
|
||||
provider text not null,
|
||||
event_id text not null,
|
||||
unique(provider, event_id)
|
||||
)`,
|
||||
)
|
||||
await Promise.all(
|
||||
Array.from({ length: 8 }, () =>
|
||||
pool.query(
|
||||
`INSERT INTO ${tableName} (provider, event_id)
|
||||
VALUES ('integration', 'replay-1')
|
||||
ON CONFLICT (provider, event_id) DO NOTHING`,
|
||||
),
|
||||
),
|
||||
)
|
||||
const result = await pool.query(`SELECT COUNT(*)::int AS count FROM ${tableName}`)
|
||||
assert.equal(result.rows[0].count, 1)
|
||||
} finally {
|
||||
await pool.end()
|
||||
}
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user