[FIX] hw_drivers: Lost IoT events

Events coming from the IoT Box were lost in two cases:

1. Create a listener for device 1
2. Send an action to device 1
--> If the action arrives before the listener the event is never sent
to the DB

1. Setup up two listeners for devices 1 & 2
2. After a few seconds, send two consecutive actions to devices 1 & 2
--> Everytime a longpolling request arrives, a new threading.Event
object is created. The first action sets the event, then, before the
new longpolling request arrives, the second action sets the same event,
which is overwritten once the new longpolling request arrives.

We now maintain a list of events, and when a longpolling request
arrives on the IoT Box, we make sure that all events that occured in
the last 5 seconds were received by the DB. If no events were pending,
we wait 50 seconds to check if a new one pops up.

Taskid: 2320958
X-original-commit: e3260712ce96a8d81bf807574c334d92c37c6ae4
This commit is contained in:
Antoine Prieels
2020-11-16 16:01:21 +00:00
parent 91bbdf41f4
commit f3b5bf6b3f
2 changed files with 22 additions and 3 deletions
+13
View File
@@ -6,6 +6,7 @@ import json
import logging
import os
import subprocess
import time
from odoo import http, tools
from odoo.http import send_file
@@ -48,6 +49,18 @@ class DriverController(http.Controller):
listener is a dict in witch there are a sessions_id and a dict of device_identifier to listen
"""
req = event_manager.add_request(listener)
# Search for previous events and remove events older than 5 seconds
oldest_time = time.time() - 5
for event in list(event_manager.events):
if event['time'] < oldest_time:
del event_manager.events[0]
continue
if event['device_identifier'] in listener['devices'] and event['time'] > listener['last_event']:
event['session_id'] = req['session_id']
return event
# Wait for new event
if req['event'].wait(50):
req['event'].clear()
req['result']['session_id'] = req['session_id']
+9 -3
View File
@@ -7,6 +7,7 @@ import time
class EventManager(object):
def __init__(self):
self.events = []
self.sessions = {}
def _delete_expired_sessions(self, max_time=70):
@@ -37,10 +38,15 @@ class EventManager(object):
return self.sessions[listener['session_id']]
def device_changed(self, device):
event = {
**device.data,
'device_identifier': device.device_identifier,
'time': time.time(),
}
self.events.append(event)
for session in self.sessions:
if device.device_identifier in self.sessions[session]['devices']:
self.sessions[session]['result'] = device.data
self.sessions[session]['result']['device_identifier'] = device.device_identifier
if device.device_identifier in self.sessions[session]['devices'] and not self.sessions[session]['event'].isSet():
self.sessions[session]['result'] = event
self.sessions[session]['event'].set()