feat(follow-location): alert-geosync
All checks were successful
/ build (map[dockerfile:./services/app/Dockerfile name:app]) (push) Successful in 1m8s
/ build (map[dockerfile:./services/tasks/Dockerfile name:tasks]) (push) Successful in 2m33s
/ build (map[dockerfile:./services/api/Dockerfile name:api]) (push) Successful in 2m58s
/ build (map[dockerfile:./services/files/Dockerfile name:files]) (push) Successful in 2m47s
/ build (map[dockerfile:./services/watchers/Dockerfile name:watchers]) (push) Successful in 2m31s
/ build (map[dockerfile:./services/hasura/Dockerfile name:hasura]) (push) Successful in 1m40s
/ build (map[dockerfile:./services/web/Dockerfile name:web]) (push) Successful in 2m21s
/ deploy (push) Successful in 16s

This commit is contained in:
Jo 2025-06-01 09:58:01 +02:00
parent 7ee0a75b50
commit 227b53cd39
6 changed files with 159 additions and 39 deletions

View file

@ -0,0 +1,64 @@
const async = require("async")
const { ctx } = require("@modjo/core")
const tasks = require("~/tasks")
module.exports = async function alertGeolocSync(params) {
const { addTask } = ctx.require("amqp")
const redis = ctx.require("redisHotGeodata")
const {
alertId,
coordinates,
userId,
deviceId,
notifyAround = false,
notifyRelatives = false,
isLast = false,
} = params
return async.parallel([
async () => {
if (coordinates && coordinates.length === 2) {
const [longitude, latitude] = coordinates
return redis.geoadd("alert", longitude, latitude, alertId)
}
},
async () =>
notifyAround &&
userId &&
deviceId &&
addTask(tasks.GEOCODE_ALERT, {
alertId,
userId,
deviceId,
coordinates,
}),
async () =>
notifyRelatives &&
userId &&
addTask(tasks.RELATIVE_ALERT, {
alertId,
userId,
}),
async () =>
coordinates &&
coordinates.length === 2 &&
addTask(tasks.GEOCODE_ALERT_GUESS_ADDRESS, {
alertId,
coordinates,
isLast,
}),
async () =>
coordinates &&
coordinates.length === 2 &&
addTask(tasks.GEOCODE_ALERT_WHAT3WORDS, {
alertId,
coordinates,
isLast,
}),
])
}

View file

@ -0,0 +1,9 @@
/**
* Common task constants for geocoding operations
*/
module.exports = {
GEOCODE_ALERT_GUESS_ADDRESS: "geocodeAlertGuessAddress",
GEOCODE_ALERT_WHAT3WORDS: "geocodeAlertWhat3Words",
GEOCODE_ALERT: "geocodeAlert",
RELATIVE_ALERT: "relativeAlert",
}

View file

@ -1,16 +1,13 @@
const async = require("async")
const { ctx } = require("@modjo/core")
const { reqCtx } = require("@modjo/express/ctx")
const { nanoid } = require("nanoid")
// const natoUuid = require("utils/nato-alphabet/uuid")
const wordsUuid = require("utils/words-id/uuid")
const tasks = require("~/tasks")
const alertGeosync = require("common/oapi/services/alert-geosync")
module.exports = function () {
const sql = ctx.require("postgres")
const { addTask } = ctx.require("amqp")
const redis = ctx.require("redisHotGeodata")
// ;(async () => {
// for (const row of await sql`SELECT id,uuid FROM alert`) {
@ -74,36 +71,15 @@ module.exports = function () {
`
})
await async.parallel([
async () => {
const [longitude, latitude] = coordinates
return redis.geoadd("alert", longitude, latitude, alertId)
},
async () =>
notifyAround &&
addTask(tasks.GEOCODE_ALERT, {
alertId,
userId,
deviceId,
coordinates,
}),
async () =>
notifyRelatives &&
addTask(tasks.RELATIVE_ALERT, {
alertId,
userId,
}),
async () =>
addTask(tasks.GEOCODE_ALERT_GUESS_ADDRESS, {
alertId,
coordinates,
}),
async () =>
addTask(tasks.GEOCODE_ALERT_WHAT3WORDS, {
alertId,
coordinates,
}),
])
await alertGeosync({
alertId,
coordinates,
userId,
deviceId,
notifyAround,
notifyRelatives,
isLast: false,
})
return { alertId, accessCode, code }
}

View file

@ -11,10 +11,24 @@ module.exports = async function () {
const sql = ctx.require("postgres")
const { coordinates, alertId } = params
const { coordinates, alertId, isLast = false } = params
// Check if coordinates is valid
if (
!coordinates ||
!Array.isArray(coordinates) ||
coordinates.length !== 2
) {
logger.error(
{ params },
"Invalid coordinates for geocodeAlertGuessAddress"
)
return
}
const nominatimResult = await nominatimReverse(coordinates)
if (!nominatimResult) {
logger.error({ params }, "Failed to get nominatim result")
return
}
const { display_name: address } = nominatimResult
@ -23,11 +37,13 @@ module.exports = async function () {
return
}
const fields = isLast ? { last_address: address } : { address }
await sql`
UPDATE
"alert"
SET
"address" = ${address}
${sql(fields)}
WHERE
"id" = ${alertId}
`

View file

@ -11,17 +11,38 @@ module.exports = async function () {
const sql = ctx.require("postgres")
const { coordinates, alertId } = params
const { coordinates, alertId, isLast = false } = params
// Check if coordinates is valid
if (
!coordinates ||
!Array.isArray(coordinates) ||
coordinates.length !== 2
) {
logger.error(
{ params },
"Invalid coordinates for geocodeAlertWhat3words"
)
return
}
const what3wordsResult = await what3words(coordinates)
if (!what3wordsResult) {
logger.error({ params }, "Failed to get what3words result")
return
}
const { words, nearestPlace } = what3wordsResult
const fields = isLast
? { last_what3words: words, last_nearest_place: nearestPlace }
: { what3words: words, nearest_place: nearestPlace }
await sql`
UPDATE
"alert"
SET
"what3words" = ${words},
"nearest_place" = ${nearestPlace}
${sql(fields)}
WHERE
"id" = ${alertId}
`

View file

@ -3,6 +3,7 @@ const async = require("async")
const { ctx } = require("@modjo/core")
// const { taskCtx } = require("@modjo/microservice-worker/ctx")
const alertGeosync = require("common/oapi/services/alert-geosync")
const { ignoreForeignKeyViolation } = require("common/libs/pg/ignoreErrors")
const {
DEVICE_RADIUS_ALL_DEFAULT,
@ -116,6 +117,39 @@ module.exports = async function () {
AND "follow_location" = TRUE
`
},
async () => {
if (!device.followLocation) {
return
}
// Get all open alerts for this device that follow location
const alerts = await sql`
SELECT
"id",
"notify_around"
FROM
"alert"
WHERE
"device_id" = ${deviceId}
AND "state" = 'open'
AND "follow_location" = TRUE
`
// Update geolocation data for each alert
await Promise.all(
alerts.map((alert) =>
alertGeosync({
alertId: alert.id,
coordinates,
userId,
deviceId,
notifyAround: alert.notifyAround,
notifyRelatives: false,
isLast: true,
})
)
)
},
])
// elapsed.end()