as-services/services/tasks/src/queues/intersect-alert-device.js
2025-08-24 11:18:25 +02:00

94 lines
2.5 KiB
JavaScript

// const { getDistance } = require("geolib")
// const timeLogger = require("utils/debug/time-logger")
const yaRetry = require("ya-retry")
const { ctx } = require("@modjo/core")
const { taskCtx } = require("@modjo/microservice-worker/ctx")
const { ignoreForeignKeyViolation } = require("common/libs/pg/ignoreErrors")
const { DEVICE_RADIUS_REACH_DEFAULT } = require("~/geocode/config")
module.exports = async function () {
/*
goal: avoid race condition between alert geocode event and device move geocode event,
triggered when device move and alert in maximum area does not have a radius already defined
*/
async function intersectAlertDevice(params) {
const sql = ctx.require("postgres")
const { deviceId, alertId, userId, distance, coordinates } = params
const [alert] = await sql`
SELECT
"alert"."radius"
FROM
"alert"
WHERE
"id" = ${alertId}
`
if (!alert) {
// alert removed
return
}
if (!alert.radius) {
throw new Error("alert radius not defined")
}
const [device] = await sql`
SELECT
"device"."radius_reach"
FROM
"device"
WHERE
"device"."id" = ${deviceId}
`
if (!device) {
// device removed
return
}
let { radiusReach } = device
if (!radiusReach) {
radiusReach = DEVICE_RADIUS_REACH_DEFAULT
}
const distanceMax = Math.min(radiusReach, alert.radius)
if (distance <= distanceMax) {
const locationJSON = JSON.stringify({
type: "Point",
coordinates,
})
const initialLocation = sql`ST_GeomFromGeoJSON(${locationJSON})`
const reason = "around"
const geomatchMethod = "move-deferred"
await ignoreForeignKeyViolation(sql`
INSERT INTO "alerting" ("user_id", "alert_id", "device_id", "initial_location", "initial_distance", "reason", "geomatch_method")
VALUES (${userId}, ${alertId}, ${deviceId}, ${initialLocation}, ${distance}, ${reason}, ${geomatchMethod})
ON CONFLICT ("user_id", "alert_id")
DO NOTHING
`)
}
}
return Object.assign(
async function intersectAlertDeviceWithRetry(params) {
const logger = taskCtx.require("logger")
logger.info("queue hanlder intersectAlertDevice", params)
await yaRetry(
async (_bail) => {
return intersectAlertDevice(params)
},
{
retries: 10,
minTimeout: 2000,
}
)
},
{
dedupOptions: { enabled: true },
}
)
}