fix(api): нормализовать дату сохранённого снимка Internet path
This commit is contained in:
1 parent
4d88b97d49
commit
673e5ba444
7 files changed
+276
-8
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import type { FastifyPluginAsyncZod } from "@fastify/type-provider-zod"
|
||||
import { readStoredInternetPathPayload } from "../services/internet-path-snapshot.js"
|
||||
import { mapStoredInternetPathResponse } from "../services/internet-path-snapshot.js"
|
||||
import { refreshScheduler } from "../services/scheduler.js"
|
||||
import {
|
||||
getInternetPathSettings,
|
||||
@@ -48,16 +48,11 @@ const internetPathRoutes: FastifyPluginAsyncZod = async (app) => {
|
||||
app.get("/internet-path/latest", async (_req, reply) => {
|
||||
const row = await getLatestInternetPathSnapshot()
|
||||
if (!row) return reply.send({ snapshot: null })
|
||||
let payload: object
|
||||
try {
|
||||
payload = readStoredInternetPathPayload(row.payloadJson)
|
||||
return reply.send(mapStoredInternetPathResponse(row))
|
||||
} catch {
|
||||
return reply.code(502).send({error: "Сохранённый снимок Internet path повреждён"})
|
||||
}
|
||||
return reply.send({
|
||||
snapshot: payload,
|
||||
sampledAt: row.sampledAt,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import assert from "node:assert/strict"
|
||||
import {collectConfirmedInternetPath, readInternetPathRows, readStoredInternetPathPayload} from "./internet-path-snapshot.js"
|
||||
import {collectConfirmedInternetPath, readInternetPathRows, readStoredInternetPathPayload, mapStoredInternetPathResponse} from "./internet-path-snapshot.js"
|
||||
const servers=[{id:1,type:"home-router",enabled:true},{id:2,type:"home-router",enabled:false},{id:3,type:"exit-node",enabled:true}]
|
||||
const sampledAt="2026-10-04T00:00:00Z"
|
||||
const defaults={servers:async()=>servers,gre:async()=>[],filters:async()=>[],speed:async()=>[],route:async(id:number)=>{assert.equal(id,1);return {gateway:null,routingMark:null}},wan:async(id:number)=>{assert.equal(id,1);return {defaultGateway:null,defaultInterface:null,uplinks:[]}}}
|
||||
@@ -26,3 +26,12 @@ for(const [fields,row] of [[ ["dst-address"],{"message":"denied"} ],[["interface
|
||||
assert.deepEqual(readInternetPathRows([],"routes",["dst-address"]),[])
|
||||
assert.equal(readInternetPathRows([{ "dst-address":"0.0.0.0/0",active:"true" }],"routes",["dst-address"]).length,1)
|
||||
assert.equal(readInternetPathRows([{ ".id":"*1",name:"gre", "local-address":"0.0.0.0","remote-address":"192.0.2.2" }],"gre",[".id","name","local-address","remote-address"]).length,1)
|
||||
|
||||
for (const stored of ["2026-10-04 07:00:00+07", "2026-10-04T00:00:00Z"]) {
|
||||
const response=mapStoredInternetPathResponse({payloadJson:good,sampledAt:stored})
|
||||
assert.equal(response.sampledAt,"2026-10-04T00:00:00.000Z")
|
||||
assert.deepEqual(response.snapshot,good)
|
||||
}
|
||||
for (const invalid of ["", "bad", null]) assert.throws(()=>mapStoredInternetPathResponse({payloadJson:good,sampledAt:invalid as string}))
|
||||
assert.throws(()=>mapStoredInternetPathResponse({payloadJson:"bad",sampledAt}))
|
||||
console.log("internet path HTTP timestamp: PostgreSQL/ISO instant preserved; invalid metadata rejected")
|
||||
@@ -30,3 +30,9 @@ export function readStoredInternetPathPayload(raw: unknown): object {
|
||||
if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new Error("Сохранённый снимок Internet path повреждён")
|
||||
return payload
|
||||
}
|
||||
|
||||
/** PostgreSQL string-mode timestamps must be normalized at the HTTP boundary. */
|
||||
export function mapStoredInternetPathResponse(row: { payloadJson: unknown; sampledAt: string }) {
|
||||
if (typeof row.sampledAt !== "string" || !row.sampledAt.trim()) throw new Error("Сохранённая дата Internet path повреждена")
|
||||
return { snapshot: readStoredInternetPathPayload(row.payloadJson), sampledAt: new Date(row.sampledAt).toISOString() }
|
||||
}
|
||||
Reference in new issue
Block a user