update metadata asynchronously when download finishes

This commit is contained in:
Jakob Ketterl 2021-08-06 21:23:44 +02:00
parent 3ccb4a11d2
commit 8e945d4149

View File

@ -17,7 +17,7 @@ class Enricher(ABC):
self.parser = parser self.parser = parser
@abstractmethod @abstractmethod
def enrich(self, meta): def enrich(self, meta, callback):
pass pass
@ -58,9 +58,15 @@ class RadioIDEnricher(Enricher):
super().__init__(parser) super().__init__(parser)
self.mode = mode self.mode = mode
self.threads = {} self.threads = {}
self.callbacks = {}
def _fillCache(self, id): def _fillCache(self, id):
RadioIDCache.getSharedInstance().put(self.mode, id, self._downloadRadioIdData(id)) data = self._downloadRadioIdData(id)
RadioIDCache.getSharedInstance().put(self.mode, id, data)
if id in self.callbacks:
while self.callbacks[id]:
self.callbacks[id].pop()(data)
del self.callbacks[id]
del self.threads[id] del self.threads[id]
def _downloadRadioIdData(self, id): def _downloadRadioIdData(self, id):
@ -80,7 +86,7 @@ class RadioIDEnricher(Enricher):
return None return None
def enrich(self, meta): def enrich(self, meta, callback):
config_key = "digital_voice_{}_id_lookup".format(self.mode) config_key = "digital_voice_{}_id_lookup".format(self.mode)
if not Config.get()[config_key]: if not Config.get()[config_key]:
return meta return meta
@ -92,6 +98,15 @@ class RadioIDEnricher(Enricher):
if id not in self.threads: if id not in self.threads:
self.threads[id] = threading.Thread(target=self._fillCache, args=[id], daemon=True) self.threads[id] = threading.Thread(target=self._fillCache, args=[id], daemon=True)
self.threads[id].start() self.threads[id].start()
if id not in self.callbacks:
self.callbacks[id] = []
def onFinish(data):
if data is not None:
meta["additional"] = data
callback(meta)
self.callbacks[id].append(onFinish)
return meta return meta
data = cache.get(self.mode, id) data = cache.get(self.mode, id)
if data is not None: if data is not None:
@ -100,7 +115,7 @@ class RadioIDEnricher(Enricher):
class YsfMetaEnricher(Enricher): class YsfMetaEnricher(Enricher):
def enrich(self, meta): def enrich(self, meta, callback):
for key in ["source", "up", "down", "target"]: for key in ["source", "up", "down", "target"]:
if key in meta: if key in meta:
meta[key] = meta[key].strip() meta[key] = meta[key].strip()
@ -114,7 +129,7 @@ class YsfMetaEnricher(Enricher):
class DStarEnricher(Enricher): class DStarEnricher(Enricher):
def enrich(self, meta): def enrich(self, meta, callback):
for key in ["lat", "lon"]: for key in ["lat", "lon"]:
if key in meta: if key in meta:
meta[key] = float(meta[key]) meta[key] = float(meta[key])
@ -154,14 +169,22 @@ class MetaParser(Parser):
"DSTAR": DStarEnricher(self), "DSTAR": DStarEnricher(self),
"NXDN": RadioIDEnricher("nxdn", self), "NXDN": RadioIDEnricher("nxdn", self),
} }
self.currentMetaData = None
def parse(self, raw: str): def parse(self, raw: str):
for meta in raw.split("\n"): for meta in raw.split("\n"):
fields = meta.split(";") fields = meta.split(";")
meta = {v[0]: ":".join(v[1:]) for v in map(lambda x: x.split(":"), fields) if v[0] != ""} meta = {v[0]: ":".join(v[1:]) for v in map(lambda x: x.split(":"), fields) if v[0] != ""}
self.currentMetaData = None
if "protocol" in meta: if "protocol" in meta:
protocol = meta["protocol"] protocol = meta["protocol"]
if protocol in self.enrichers: if protocol in self.enrichers:
meta = self.enrichers[protocol].enrich(meta) self.currentMetaData = meta = self.enrichers[protocol].enrich(meta, self.receive)
self.handler.write_metadata(meta) self.handler.write_metadata(meta)
def receive(self, meta):
# we may have moved on in the meantime
if meta is not self.currentMetaData:
return
self.handler.write_metadata(meta)