From 72498b3bbcc434f58a22f43fa7095cf160f9c56e Mon Sep 17 00:00:00 2001 From: A_D Date: Wed, 22 Jul 2020 16:26:06 +0200 Subject: [PATCH 1/5] Switched to using a timer for inara updates This adds a new thread that will run in a loop sending inara events once ever 30 seconds. The old method of sending once for "special" events has been removed. --- plugins/inara.py | 56 ++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/plugins/inara.py b/plugins/inara.py index bfff9e5d..7cf0919e 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -4,6 +4,7 @@ from collections import OrderedDict import json +from typing import Any, Union import requests import sys import time @@ -26,7 +27,7 @@ FAKE = ['CQC', 'Training', 'Destination'] # Fake systems that shouldn't be sent CREDIT_RATIO = 1.05 # Update credits if they change by 5% over the course of a session -this = sys.modules[__name__] # For holding module globals +this: Any = sys.modules[__name__] # For holding module globals this.session = requests.Session() this.queue = Queue() # Items to be sent to Inara by worker thread this.lastlocation = None # eventData from the last Commander's Flight Log event @@ -50,7 +51,8 @@ this.fleet = None this.shipswap = False # just swapped ship this.last_update_time = time.time() # last time we updated (set to now because we're going to update quickly) -FLOOD_LIMIT_SECONDS = 45 # minimum time between sending non-major cargo triggered messages +FLOOD_LIMIT_SECONDS = 30 # minimum time between sending events +this.timer_run = True # Main window clicks @@ -85,6 +87,10 @@ def plugin_start3(plugin_dir): this.thread = Thread(target = worker, name = 'Inara worker') this.thread.daemon = True this.thread.start() + + this.timer_thread = Thread(target=call_timer, name='Inara timer') + this.timer_thread.daemon = True + this.timer_thread.start() return 'Inara' def plugin_app(parent): @@ -95,12 +101,14 @@ def plugin_app(parent): def plugin_stop(): # Send any unsent events - call() + call(force=True) # Signal thread to close and wait for it this.queue.put(None) this.thread.join() this.thread = None + this.timer_run = False + def plugin_prefs(parent, cmdr, is_beta): PADX = 10 @@ -188,7 +196,7 @@ def journal_entry(cmdr, is_beta, system, station, entry, state): # Send any unsent events when switching accounts if cmdr and cmdr != this.cmdr: - call() + call(force=True) this.cmdr = cmdr this.FID = state['FID'] @@ -245,8 +253,6 @@ def journal_entry(cmdr, is_beta, system, station, entry, state): if config.getint('inara_out') and not is_beta and not this.multicrew and credentials(cmdr): try: - old_events = len(this.events) # Will only send existing events if we add a new event below - # Dump starting state to Inara if (this.newuser or @@ -305,6 +311,8 @@ def journal_entry(cmdr, is_beta, system, station, entry, state): this.loadout = make_loadout(state) add_event('setCommanderShipLoadout', entry['timestamp'], this.loadout) + + call() # Call here just to be sure that if we can send, we do, otherwise it'll get it in the next tick # Promotions @@ -437,23 +445,17 @@ def journal_entry(cmdr, is_beta, system, station, entry, state): # if our cargo differers from last we checked, we're at a station, # and our flood limit isnt covered, queue an update should_poll = this.cargo != cargo and time.time() - this.last_update_time > FLOOD_LIMIT_SECONDS - - # Send event(s) to Inara - if entry['event'] == 'ShutDown' or len(this.events) > old_events or should_poll: - # Send cargo and materials if changed - if this.cargo != cargo: - add_event('setCommanderInventoryCargo', entry['timestamp'], cargo) - this.cargo = cargo - materials = [] - for category in ['Raw', 'Manufactured', 'Encoded']: - materials.extend([ OrderedDict([('itemName', k), ('itemCount', state[category][k])]) for k in sorted(state[category]) ]) - if this.materials != materials: - add_event('setCommanderInventoryMaterials', entry['timestamp'], materials) - this.materials = materials - - # Queue a call to Inara - call() + # Send cargo and materials if changed + if this.cargo != cargo: + add_event('setCommanderInventoryCargo', entry['timestamp'], cargo) + this.cargo = cargo + materials = [] + for category in ['Raw', 'Manufactured', 'Encoded']: + materials.extend([ OrderedDict([('itemName', k), ('itemCount', state[category][k])]) for k in sorted(state[category]) ]) + if this.materials != materials: + add_event('setCommanderInventoryMaterials', entry['timestamp'], materials) + this.materials = materials except Exception as e: logger.debug('Adding events', exc_info=e) @@ -856,12 +858,20 @@ def add_event(name, timestamp, data): ('eventData', data), ])) +def call_timer(wait=FLOOD_LIMIT_SECONDS): + while this.timer_run: + time.sleep(wait) + if this.timer_run: # check again in here just in case we're closing and the stars align + call() # Queue a call to Inara, handled in Worker thread -def call(callback=None): +def call(callback=None, force=False): if not this.events: return + if (time.time() - this.last_update_time) <= FLOOD_LIMIT_SECONDS and not force: + return + this.last_update_time = time.time() data = OrderedDict([ From 34760683e58fd33e15a319060b30ed5666372fd3 Mon Sep 17 00:00:00 2001 From: A_D Date: Thu, 23 Jul 2020 16:47:29 +0200 Subject: [PATCH 2/5] added some debug logging --- plugins/inara.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/inara.py b/plugins/inara.py index 7cf0919e..4242dcdf 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -861,6 +861,7 @@ def add_event(name, timestamp, data): def call_timer(wait=FLOOD_LIMIT_SECONDS): while this.timer_run: time.sleep(wait) + print("INARA: TICK") if this.timer_run: # check again in here just in case we're closing and the stars align call() @@ -873,7 +874,7 @@ def call(callback=None, force=False): return this.last_update_time = time.time() - + print(f"INARA: {time.asctime()}sending {len(this.events)} entries to inara (call)") data = OrderedDict([ ('header', OrderedDict([ ('appName', applongname), @@ -896,6 +897,8 @@ def worker(): else: (url, data, callback) = item + print(f"INARA: {time.asctime()}sending {len(data['events'])} entries to inara (worker)") + retrying = 0 while retrying < 3: try: From 340f8928b353aca6d381a9d60a419aa112100960 Mon Sep 17 00:00:00 2001 From: A_D Date: Thu, 23 Jul 2020 18:38:55 +0200 Subject: [PATCH 3/5] switched to using config for last update time --- plugins/inara.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/plugins/inara.py b/plugins/inara.py index 4242dcdf..a8b3ee8d 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -50,7 +50,9 @@ this.loadout = None this.fleet = None this.shipswap = False # just swapped ship -this.last_update_time = time.time() # last time we updated (set to now because we're going to update quickly) +# last time we updated, if unset in config this is 0, which means an instant update +LAST_UPDATE_CONF_KEY = 'inara_last_update' +# this.last_update_time = config.getint(LAST_UPDATE_CONF_KEY) FLOOD_LIMIT_SECONDS = 30 # minimum time between sending events this.timer_run = True @@ -442,10 +444,6 @@ def journal_entry(cmdr, is_beta, system, station, entry, state): cargo = [OrderedDict([('itemName', k), ('itemCount', state['Cargo'][k])]) for k in sorted(state['Cargo'])] - # if our cargo differers from last we checked, we're at a station, - # and our flood limit isnt covered, queue an update - should_poll = this.cargo != cargo and time.time() - this.last_update_time > FLOOD_LIMIT_SECONDS - # Send cargo and materials if changed if this.cargo != cargo: add_event('setCommanderInventoryCargo', entry['timestamp'], cargo) @@ -861,7 +859,7 @@ def add_event(name, timestamp, data): def call_timer(wait=FLOOD_LIMIT_SECONDS): while this.timer_run: time.sleep(wait) - print("INARA: TICK") + print(f"INARA: {time.asctime()} TICK") if this.timer_run: # check again in here just in case we're closing and the stars align call() @@ -870,11 +868,11 @@ def call(callback=None, force=False): if not this.events: return - if (time.time() - this.last_update_time) <= FLOOD_LIMIT_SECONDS and not force: + if (time.time() - config.getint(LAST_UPDATE_CONF_KEY)) <= FLOOD_LIMIT_SECONDS and not force: return - this.last_update_time = time.time() - print(f"INARA: {time.asctime()}sending {len(this.events)} entries to inara (call)") + config.set(LAST_UPDATE_CONF_KEY, int(time.time())) + print(f"INARA: {time.asctime()} sending {len(this.events)} entries to inara (call)") data = OrderedDict([ ('header', OrderedDict([ ('appName', applongname), @@ -897,7 +895,7 @@ def worker(): else: (url, data, callback) = item - print(f"INARA: {time.asctime()}sending {len(data['events'])} entries to inara (worker)") + print(f"INARA: {time.asctime()} sending {len(data['events'])} entries to inara (worker)") retrying = 0 while retrying < 3: From bb817eee3b83348e21dfbf89f88332471bf0ae7f Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 24 Jul 2020 11:43:40 +0200 Subject: [PATCH 4/5] removed outdated comment --- plugins/inara.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/inara.py b/plugins/inara.py index a8b3ee8d..43fd5880 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -459,10 +459,6 @@ def journal_entry(cmdr, is_beta, system, station, entry, state): logger.debug('Adding events', exc_info=e) return str(e) - # - # Events that don't need to be sent immediately but will be sent on the next mandatory event - # - # Send credits and stats to Inara on startup only - otherwise may be out of date if entry['event'] == 'LoadGame': add_event('setCommanderCredits', entry['timestamp'], From d4299c224f2a783d3380b9ca244c05b1823440e6 Mon Sep 17 00:00:00 2001 From: A_D Date: Mon, 27 Jul 2020 15:12:32 +0200 Subject: [PATCH 5/5] dont force a send on exit just try and send if we can --- plugins/inara.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/inara.py b/plugins/inara.py index 43fd5880..aa7e7b90 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -103,7 +103,8 @@ def plugin_app(parent): def plugin_stop(): # Send any unsent events - call(force=True) + call() + time.sleep(0.1) # Sleep for 100ms to allow call to go out, and to force a context switch to our other threads # Signal thread to close and wait for it this.queue.put(None) this.thread.join()