feat(follow-location): geocode move + migrations
All checks were successful
/ build (map[dockerfile:./services/tasks/Dockerfile name:tasks]) (push) Successful in 2m33s
/ build (map[dockerfile:./services/watchers/Dockerfile name:watchers]) (push) Successful in 2m25s
/ build (map[dockerfile:./services/api/Dockerfile name:api]) (push) Successful in 1m40s
/ build (map[dockerfile:./services/app/Dockerfile name:app]) (push) Successful in 1m48s
/ build (map[dockerfile:./services/files/Dockerfile name:files]) (push) Successful in 1m55s
/ build (map[dockerfile:./services/hasura/Dockerfile name:hasura]) (push) Successful in 2m34s
/ build (map[dockerfile:./services/web/Dockerfile name:web]) (push) Successful in 2m34s
/ deploy (push) Successful in 10s

This commit is contained in:
devthejo 2025-05-30 18:12:23 +02:00
parent 91d3258533
commit e40b939144
8 changed files with 110 additions and 9 deletions

View file

@ -9,6 +9,8 @@ configuration:
custom_name: createdAt
fcm_token:
custom_name: fcmToken
follow_location:
custom_name: followLocation
notification_alert_level:
custom_name: notificationAlertLevel
phone_model:
@ -27,6 +29,7 @@ configuration:
altitude_accuracy: altitudeAccuracy
created_at: createdAt
fcm_token: fcmToken
follow_location: followLocation
notification_alert_level: notificationAlertLevel
phone_model: phoneModel
preferred_emergency_call: preferredEmergencyCall

View file

@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."device" add column "follow_location" boolean
-- not null default 'false';

View file

@ -0,0 +1,2 @@
alter table "public"."device" add column "follow_location" boolean
not null default 'false';

View file

@ -0,0 +1,5 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE INDEX ON alert(device_id)
-- WHERE state = 'open'
-- AND follow_location = TRUE;

View file

@ -0,0 +1,3 @@
CREATE INDEX ON alert(device_id)
WHERE state = 'open'
AND follow_location = TRUE;

View file

@ -0,0 +1,35 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE FUNCTION trigger_alert_update_propagate_follow_location_to_device() RETURNS trigger LANGUAGE plpgsql AS $$
-- DECLARE
-- should_follow boolean;
-- affected_device int := COALESCE(NEW.device_id, OLD.device_id);
-- BEGIN
-- IF affected_device IS NULL THEN
-- RETURN NEW;
-- END IF;
--
-- -- compute once
-- SELECT EXISTS(
-- SELECT 1
-- FROM alert a
-- WHERE a.device_id = affected_device
-- AND a.state = 'open'
-- AND a.follow_location = TRUE
-- ) INTO should_follow;
--
-- -- only update when it actually changes
-- UPDATE device d
-- SET follow_location = should_follow
-- WHERE d.id = affected_device
-- AND d.follow_location IS DISTINCT FROM should_follow;
--
-- RETURN NEW;
-- END;
-- $$;
--
-- CREATE TRIGGER trigger_alert_update_propagate_follow_location_to_device_after_update
-- AFTER INSERT OR UPDATE OR DELETE
-- ON alert
-- FOR EACH ROW
-- EXECUTE FUNCTION trigger_alert_update_propagate_follow_location_to_device();

View file

@ -0,0 +1,33 @@
CREATE FUNCTION trigger_alert_update_propagate_follow_location_to_device() RETURNS trigger LANGUAGE plpgsql AS $$
DECLARE
should_follow boolean;
affected_device int := COALESCE(NEW.device_id, OLD.device_id);
BEGIN
IF affected_device IS NULL THEN
RETURN NEW;
END IF;
-- compute once
SELECT EXISTS(
SELECT 1
FROM alert a
WHERE a.device_id = affected_device
AND a.state = 'open'
AND a.follow_location = TRUE
) INTO should_follow;
-- only update when it actually changes
UPDATE device d
SET follow_location = should_follow
WHERE d.id = affected_device
AND d.follow_location IS DISTINCT FROM should_follow;
RETURN NEW;
END;
$$;
CREATE TRIGGER trigger_alert_update_propagate_follow_location_to_device_after_update
AFTER INSERT OR UPDATE OR DELETE
ON alert
FOR EACH ROW
EXECUTE FUNCTION trigger_alert_update_propagate_follow_location_to_device();

View file

@ -28,11 +28,12 @@ module.exports = async function () {
const [device] = await sql`
SELECT
"device"."radius_all",
"device"."radius_reach"
"device"."radius_reach",
"device"."follow_location"
FROM
"device"
" device "
WHERE
"device"."id" = ${deviceId}
" device "." id " = " gajus - eslint - plugin - sql "
`
if (!device) {
@ -61,21 +62,22 @@ module.exports = async function () {
deviceId,
})
const locationJSON = JSON.stringify({
type: "Point",
coordinates,
})
const deviceSqlGeopoint = sql`ST_GeomFromGeoJSON(${locationJSON})`
await async.parallel([
async () => {
const insertRows = Object.entries(alertList).map(
([alertId, { distance }]) => {
const locationJSON = JSON.stringify({
type: "Point",
coordinates,
})
const initialLocation = sql`ST_GeomFromGeoJSON(${locationJSON})`
return {
userId,
alertId,
deviceId,
initialDistance: distance,
initialLocation,
initialLocation: deviceSqlGeopoint,
reason: "around",
geomatchMethod: "move",
}
@ -98,6 +100,20 @@ module.exports = async function () {
async (data) =>
addTask(INTERSECT_ALERT_DEVICE, { ...data, userId, coordinates })
),
async () => {
// if followLocation, sync the alerts with device location
if (!device.followLocation) {
return
}
await sql`
UPDATE
"alerting"
SET
"location" = ${deviceSqlGeopoint}
WHERE
"device_id" = ${deviceId}
`
},
])
// elapsed.end()