Skip to content

Commit 2aae828

Browse files
Hotfix make the lastactive sensor query faster (#59)
* Hotfix make the lastactive sensor query faster * Add last active tests
1 parent 5c2b85b commit 2aae828

File tree

6 files changed

+97
-30
lines changed

6 files changed

+97
-30
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from django.core.management import BaseCommand
2+
3+
from django.db import connection
4+
from sensorsafrica.api.models import Node, SensorLocation, LastActiveNodes
5+
6+
7+
class Command(BaseCommand):
8+
help = ""
9+
10+
def handle(self, *args, **options):
11+
with connection.cursor() as cursor:
12+
cursor.execute(
13+
"""
14+
SELECT
15+
sn.id,
16+
sn.location_id,
17+
MAX("timestamp") AS last_active_date
18+
FROM
19+
sensors_sensordata sd
20+
INNER JOIN sensors_sensor s ON s.id = sd.sensor_id
21+
INNER JOIN sensors_node sn ON sn.id = s.node_id
22+
INNER JOIN sensors_sensordatavalue sv ON sv.sensordata_id = sd.id
23+
AND sv.value_type in ('P1', 'P2')
24+
WHERE
25+
"timestamp" >= now() - INTERVAL '5 min'
26+
GROUP BY
27+
sn.id
28+
""")
29+
latest = cursor.fetchall()
30+
for data in latest:
31+
LastActiveNodes.objects.update_or_create(
32+
node=Node(pk=data[0]),
33+
location=SensorLocation(pk=data[1]),
34+
defaults={"last_data_received_at": data[2]},
35+
)

sensorsafrica/management/commands/cache_lastactive_nodes_data.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

sensorsafrica/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@
161161
"schedule": crontab(hour="*", minute=0)
162162
},
163163
"cache-lastactive-nodes-task": {
164-
"task": "sensorsafrica.tasks.cache_lastactive_nodes_data",
164+
"task": "sensorsafrica.tasks.cache_lastactive_nodes",
165165
"schedule": crontab(minute="*/5")
166166
},
167167
"cache-static-json-data": {

sensorsafrica/tasks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def archive_data():
1313

1414

1515
@shared_task
16-
def cache_lastactive_nodes_data():
17-
call_command("cache_lastactive_nodes_data")
16+
def cache_lastactive_nodes():
17+
call_command("cache_lastactive_nodes")
1818

1919

2020
@shared_task

sensorsafrica/tests/conftest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,36 @@ def additional_sensorsdatastats(sensors, locations, sensorsdatastats):
227227
from django.core.management import call_command
228228

229229
call_command("calculate_data_statistics")
230+
231+
232+
@pytest.fixture
233+
def last_active(sensors, locations, sensorsdatastats):
234+
timestamps = [
235+
timezone.now(),
236+
timezone.now() + datetime.timedelta(minutes=2),
237+
timezone.now() + datetime.timedelta(minutes=4)
238+
]
239+
sensordata = SensorData.objects.bulk_create([
240+
SensorData(
241+
sensor=sensors[0], location=locations[0], timestamp=timestamps[0]),
242+
SensorData(
243+
sensor=sensors[3], location=locations[3], timestamp=timestamps[1]),
244+
SensorData(
245+
sensor=sensors[4], location=locations[4], timestamp=timestamps[2]),
246+
])
247+
248+
SensorDataValue.objects.bulk_create([
249+
SensorDataValue(
250+
sensordata=sensordata[0], value="4", value_type="P2"),
251+
SensorDataValue(
252+
sensordata=sensordata[1], value="4", value_type="P1"),
253+
# Won't be tracked as last active
254+
SensorDataValue(
255+
sensordata=sensordata[2], value="4", value_type="Temp"),
256+
])
257+
258+
from django.core.management import call_command
259+
260+
call_command("cache_lastactive_nodes")
261+
262+
return timestamps
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import pytest
2+
import pytz
3+
4+
from rest_framework.test import APIRequestFactory
5+
from feinstaub.sensors.views import PostSensorDataView
6+
from sensorsafrica.api.models import LastActiveNodes
7+
8+
9+
@pytest.mark.django_db
10+
class TestLastActiveSensor:
11+
def test_lastactive_command(self, sensors, last_active):
12+
sensors0_node = LastActiveNodes.objects.filter(
13+
node=sensors[0].node_id
14+
).get()
15+
sensors3_node = LastActiveNodes.objects.filter(
16+
node=sensors[3].node_id
17+
).get()
18+
sensors4_node = LastActiveNodes.objects.filter(
19+
node=sensors[4].node_id
20+
).get()
21+
22+
assert sensors0_node.last_data_received_at == last_active[0]
23+
assert sensors3_node.last_data_received_at == last_active[1]
24+
# Sensor is last active when they send the P1 and P2
25+
# Sensor[4] sent a none P1/P2 at timestamp last_active[2]
26+
assert sensors4_node.last_data_received_at != last_active[2]

0 commit comments

Comments
 (0)