@7365admin1/core 3.52.5-staging.249 → 3.52.5-staging.250
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/visitor-dahua-cron-fail-closed.md +27 -0
- package/dist/index.js +49 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +49 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/visitor-dahua-sweep.test.mjs +191 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Fail closed in the visitor ANPR sweep, and remove the dead invitation transaction
|
|
6
|
+
|
|
7
|
+
`processTransactionDahuaStatus`, the hourly job that takes an expired or
|
|
8
|
+
checked-out visitor's plate off the site's ANPR camera, marked the transaction
|
|
9
|
+
`dahuaSyncStatus: "removed"` on the line after the camera call and only skipped
|
|
10
|
+
on a thrown error. `removePlateNumber` does not throw for a device failure - it
|
|
11
|
+
returns an outcome object - so a camera answering 401 or 500, or not answering
|
|
12
|
+
at all, still had the transaction recorded as removed while the visitor's plate
|
|
13
|
+
was still on the barrier. Nothing retried it either, because the query that
|
|
14
|
+
feeds the sweep skips anything already marked removed.
|
|
15
|
+
|
|
16
|
+
It now uses the same decision logic as the expired-vehicle sweep: only a
|
|
17
|
+
transaction every camera confirmed is marked removed, and the rest are logged at
|
|
18
|
+
error level naming the plate, the site and the camera, then retried on the next
|
|
19
|
+
run. Each camera is also asked for its own record id before the removal, which
|
|
20
|
+
is what the old "not found" message sniff was reaching for and what stops a
|
|
21
|
+
transaction whose record is already gone from being retried for ever.
|
|
22
|
+
|
|
23
|
+
`checkExpiredInvitation` opened a session and a transaction and then issued
|
|
24
|
+
every write without that session, never committing: the transaction protected no
|
|
25
|
+
write and the rollback rolled back nothing. Each invitation is independent, so
|
|
26
|
+
there is no invariant spanning them and nothing for a transaction to protect -
|
|
27
|
+
it is removed rather than wired up.
|
package/dist/index.js
CHANGED
|
@@ -16202,27 +16202,21 @@ function useVerificationService() {
|
|
|
16202
16202
|
}
|
|
16203
16203
|
}
|
|
16204
16204
|
async function checkExpiredInvitation() {
|
|
16205
|
-
const session = import_node_server_utils34.useAtlas.getClient()?.startSession();
|
|
16206
|
-
session?.startTransaction();
|
|
16207
16205
|
try {
|
|
16208
16206
|
const verifications = await _getByStatus("pending");
|
|
16207
|
+
const now = Date.now();
|
|
16209
16208
|
for (const verification of verifications) {
|
|
16210
|
-
|
|
16211
|
-
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
16212
|
-
if (now > expiration) {
|
|
16209
|
+
if (now > new Date(verification.expireAt).getTime()) {
|
|
16213
16210
|
await _updateStatusById(verification._id.toString(), "expired");
|
|
16214
16211
|
}
|
|
16215
16212
|
}
|
|
16216
16213
|
return "Successfully checked for expired invitations.";
|
|
16217
16214
|
} catch (error) {
|
|
16218
|
-
await session?.abortTransaction();
|
|
16219
16215
|
import_node_server_utils34.logger.log({
|
|
16220
16216
|
level: "info",
|
|
16221
16217
|
message: `Error checking expired user invitation: ${error}`
|
|
16222
16218
|
});
|
|
16223
16219
|
throw error;
|
|
16224
|
-
} finally {
|
|
16225
|
-
session?.endSession();
|
|
16226
16220
|
}
|
|
16227
16221
|
}
|
|
16228
16222
|
return {
|
|
@@ -23348,7 +23342,7 @@ function useDahuaService() {
|
|
|
23348
23342
|
}
|
|
23349
23343
|
try {
|
|
23350
23344
|
value.owner = String(value.owner ?? "").replace(/['"]/g, "").replace(/[\/\\]/g, " - ").substring(0, 15).trim() || "unknown";
|
|
23351
|
-
const
|
|
23345
|
+
const formatDahuaDate3 = (dateStr, fallbackYearsAhead = 0) => {
|
|
23352
23346
|
const date = dateStr ? new Date(dateStr) : /* @__PURE__ */ new Date();
|
|
23353
23347
|
if (!dateStr) {
|
|
23354
23348
|
date.setMinutes(date.getMinutes() - 10);
|
|
@@ -23359,8 +23353,8 @@ function useDahuaService() {
|
|
|
23359
23353
|
const pad = (num) => String(num).padStart(2, "0");
|
|
23360
23354
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
23361
23355
|
};
|
|
23362
|
-
const formattedStart =
|
|
23363
|
-
const formattedEnd =
|
|
23356
|
+
const formattedStart = formatDahuaDate3(value.start);
|
|
23357
|
+
const formattedEnd = formatDahuaDate3(value.end, 10);
|
|
23364
23358
|
const beginTime = encodeURIComponent(formattedStart);
|
|
23365
23359
|
const cancelTime = encodeURIComponent(formattedEnd);
|
|
23366
23360
|
const plateNumber = encodeURIComponent(value.plateNumber);
|
|
@@ -52014,42 +52008,55 @@ function useVisitorTransactionService() {
|
|
|
52014
52008
|
);
|
|
52015
52009
|
if (!transactions.length)
|
|
52016
52010
|
continue;
|
|
52017
|
-
const
|
|
52018
|
-
|
|
52019
|
-
|
|
52020
|
-
|
|
52021
|
-
|
|
52022
|
-
|
|
52023
|
-
|
|
52024
|
-
|
|
52025
|
-
|
|
52026
|
-
|
|
52027
|
-
|
|
52028
|
-
|
|
52029
|
-
|
|
52030
|
-
|
|
52031
|
-
|
|
52032
|
-
|
|
52033
|
-
|
|
52034
|
-
|
|
52035
|
-
|
|
52036
|
-
|
|
52037
|
-
|
|
52038
|
-
`Dahua record already missing for transaction ${transaction._id}, marking as removed.`
|
|
52011
|
+
const { deletableIds, skipped } = await sweepExpiredVehicles(
|
|
52012
|
+
transactions,
|
|
52013
|
+
{
|
|
52014
|
+
camerasForSite: async () => [camera],
|
|
52015
|
+
revoke: async (anprCamera, transaction) => {
|
|
52016
|
+
const credentials = {
|
|
52017
|
+
host: anprCamera.host,
|
|
52018
|
+
username: anprCamera.username,
|
|
52019
|
+
password: anprCamera.password,
|
|
52020
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */
|
|
52021
|
+
};
|
|
52022
|
+
let recno = String(transaction?.recNo ?? "");
|
|
52023
|
+
const plateNumber = String(transaction?.plateNumber ?? "");
|
|
52024
|
+
if (plateNumber) {
|
|
52025
|
+
try {
|
|
52026
|
+
const found = parseDahuaFind(
|
|
52027
|
+
await _getPlateNumber({
|
|
52028
|
+
...credentials,
|
|
52029
|
+
plateNumber,
|
|
52030
|
+
requireOk: true
|
|
52031
|
+
}) ?? ""
|
|
52039
52032
|
);
|
|
52040
|
-
|
|
52041
|
-
|
|
52033
|
+
if (!found.exists)
|
|
52034
|
+
return ANPR_NOTHING_TO_REVOKE;
|
|
52035
|
+
if (found.recNo)
|
|
52036
|
+
recno = found.recNo;
|
|
52037
|
+
} catch (error) {
|
|
52038
|
+
return anprRevokeThrew(error);
|
|
52042
52039
|
}
|
|
52043
|
-
import_node_server_utils134.logger.error(
|
|
52044
|
-
`Failed to remove plate for transaction ${transaction._id}`,
|
|
52045
|
-
error
|
|
52046
|
-
);
|
|
52047
52040
|
}
|
|
52048
|
-
|
|
52041
|
+
if (!recno)
|
|
52042
|
+
return ANPR_NOTHING_TO_REVOKE;
|
|
52043
|
+
return await _removePlateNumber({
|
|
52044
|
+
...credentials,
|
|
52045
|
+
recno
|
|
52046
|
+
}).catch((error) => anprRevokeThrew(error));
|
|
52047
|
+
},
|
|
52048
|
+
cameraLabel
|
|
52049
|
+
}
|
|
52050
|
+
);
|
|
52051
|
+
for (const entry of skipped) {
|
|
52052
|
+
import_node_server_utils134.logger.error(
|
|
52053
|
+
`processTransactionDahuaStatus NOT marking transaction ${entry.id} removed (plate ${JSON.stringify(
|
|
52054
|
+
entry.plateNumber
|
|
52055
|
+
)}, site ${entry.site}): ` + entry.failures.map((failure) => `${failure.camera} (${failure.reason})`).join(", ") + `. The plate may still open the barrier, so the record is left unsynced and will be retried on the next run.`
|
|
52049
52056
|
);
|
|
52050
52057
|
}
|
|
52051
|
-
if (
|
|
52052
|
-
await _updateManyDahuaSyncStatus(
|
|
52058
|
+
if (deletableIds.length > 0) {
|
|
52059
|
+
await _updateManyDahuaSyncStatus(deletableIds, "removed");
|
|
52053
52060
|
}
|
|
52054
52061
|
}
|
|
52055
52062
|
page++;
|