diff --git a/server/__main__.py b/server/__main__.py index 3df81ff1..51cc4c66 100755 --- a/server/__main__.py +++ b/server/__main__.py @@ -84,8 +84,6 @@ def main (): mylog('debug', '[MAIN] Starting loop') - - all_plugins = None while True: diff --git a/server/api.py b/server/api.py index 9191bba1..49602628 100755 --- a/server/api.py +++ b/server/api.py @@ -24,7 +24,7 @@ stop_event = threading.Event() # Event to signal thread termination #=============================================================================== # API #=============================================================================== -def update_api(db, all_plugins, isNotification=False, updateOnlyDataSources=[], is_ad_hoc_user_event=False): +def update_api(db, all_plugins, updateOnlyDataSources=[], is_ad_hoc_user_event=False): mylog('debug', ['[API] Update API starting']) # Start periodic write if not running @@ -88,13 +88,13 @@ class api_endpoint_class: self.fileName = path.split('/')[-1] self.hash = hash(json.dumps(self.jsonData)) self.debounce_interval = 5 # Time to wait before writing - self.last_update_time = current_time - datetime.timedelta(minutes=1) # Last time data was updated + self.changeDetectedWhen = None + # self.last_update_time = current_time - datetime.timedelta(minutes=1) # Last time data was updated self.is_ad_hoc_user_event = is_ad_hoc_user_event + self.needsUpdate = False # Check if the endpoint needs to be updated - found = False - changed = False - changedIndex = -1 + found = False index = 0 # Search previous endpoint states to check if API needs updating @@ -102,28 +102,27 @@ class api_endpoint_class: # Match SQL and API endpoint path if endpoint.query == self.query and endpoint.path == self.path: found = True + mylog('trace', [f'[API] api_endpoint_class: Hashes (file|old|new): ({self.fileName}|{endpoint.hash}|{self.hash})']) if endpoint.hash != self.hash: - changed = True - changedIndex = index + self.needsUpdate = True + # Only update changeDetectedWhen if it hasn't been set recently + if not self.changeDetectedWhen or current_time > (self.changeDetectedWhen + datetime.timedelta(seconds=self.debounce_interval)): + self.changeDetectedWhen = current_time # Set timestamp for change detection + if index < len(apiEndpoints): + apiEndpoints[index] = self + # check end of bounds and replace + if index < len(apiEndpoints): + apiEndpoints[index] = self index = index + 1 - - # Check if API endpoints have changed or if it's a new one - if not found or changed: - mylog('trace', [f'[API] api_endpoint_class: Updating {self.fileName}']) - - if not found: - apiEndpoints.append(self) - - elif changed and changedIndex != -1 and changedIndex < len(apiEndpoints): - # Update hash and data - apiEndpoints[changedIndex].hash = self.hash - apiEndpoints[changedIndex].jsonData = self.jsonData - - mylog('trace', [f'[API] api_endpoint_class: Updating hash {self.hash}']) - else: - mylog('none', [f'[API] ⚠ ERROR Updating {self.fileName}']) + # needs also an update if new endpoint + if not found: + self.needsUpdate = True + # Only update changeDetectedWhen if it hasn't been set recently + if not self.changeDetectedWhen or current_time > (self.changeDetectedWhen + datetime.timedelta(seconds=self.debounce_interval)): + self.changeDetectedWhen = current_time # Initialize timestamp for new endpoint + apiEndpoints.append(self) # Needs to be called for initial updates self.try_write() @@ -133,12 +132,16 @@ class api_endpoint_class: current_time = timeNowTZ() # Debugging info to understand the issue - # mylog('verbose', [f'[API] api_endpoint_class: {self.fileName} is_ad_hoc_user_event {self.is_ad_hoc_user_event} last_update_time={self.last_update_time}, debounce time={self.last_update_time + datetime.timedelta(seconds=self.debounce_interval)}.']) + # mylog('debug', [f'[API] api_endpoint_class: {self.fileName} is_ad_hoc_user_event {self.is_ad_hoc_user_event} last_update_time={self.last_update_time}, debounce time={self.last_update_time + datetime.timedelta(seconds=self.debounce_interval)}.']) # Only attempt to write if the debounce time has passed - if current_time > (self.last_update_time + datetime.timedelta(seconds=self.debounce_interval)): + if self.needsUpdate and (self.changeDetectedWhen is None or current_time > (self.changeDetectedWhen + datetime.timedelta(seconds=self.debounce_interval))): + + mylog('debug', [f'[API] api_endpoint_class: Writing {self.fileName} after debounce.']) + write_file(self.path, json.dumps(self.jsonData)) - # mylog('verbose', [f'[API] api_endpoint_class: Writing {self.fileName} after debounce.']) + + self.needsUpdate = False self.last_update_time = timeNowTZ() # Reset last_update_time after writing # Update user event execution log diff --git a/server/device.py b/server/device.py index 0350d895..f309f7a5 100755 --- a/server/device.py +++ b/server/device.py @@ -514,10 +514,10 @@ def update_devices_names (db): foundNsLookup = 0 foundNbtLookup = 0 - # Gen unknown devices - sql.execute ("SELECT * FROM Devices WHERE devName IN ('(unknown)','', '(name not found)') AND devLastIP <> '-'") - unknownDevices = sql.fetchall() - db.commitDB() + # Gen unknown devices + device_handler = Device_obj(db) + # Retrieve devices + unknownDevices = device_handler.getUnknown() # skip checks if no unknown devices if len(unknownDevices) == 0: diff --git a/server/graphql_server/graphql_schema.py b/server/graphql_server/graphql_schema.py index b45b18f4..3a5afbc4 100755 --- a/server/graphql_server/graphql_schema.py +++ b/server/graphql_server/graphql_schema.py @@ -166,7 +166,7 @@ class Query(ObjectType): if options.search: # Define static list of searchable fields searchable_fields = [ - "devName", "devMac", "devOwner", "devType", "devVendor", "devLastIP" + "devName", "devMac", "devOwner", "devType", "devVendor", "devLastIP", "devGroup", "devComments", "devLocation", "devStatus", "devSSID", "devSite", "devSourcePlugin", "devSyncHubNode" ] diff --git a/server/initialise.py b/server/initialise.py index 318c2faa..0421135d 100755 --- a/server/initialise.py +++ b/server/initialise.py @@ -383,7 +383,7 @@ def importConfigs (db, all_plugins): db.commitDB() # update only the settings datasource - update_api(db, all_plugins, False, ["settings"]) + update_api(db, all_plugins, ["settings"]) # run plugins that are modifying the config run_plugin_scripts(db, all_plugins, 'before_config_save' ) diff --git a/server/plugin.py b/server/plugin.py index 1fc9d3ac..80b6e724 100755 --- a/server/plugin.py +++ b/server/plugin.py @@ -467,7 +467,7 @@ def execute_plugin(db, all_plugins, plugin, pluginsState = plugins_state() ): pluginsState = process_plugin_events(db, plugin, pluginsState, sqlParams) # update API endpoints - update_api(db, all_plugins, False, ["plugins_events","plugins_objects", "plugins_history", "appevents"]) + update_api(db, all_plugins, ["plugins_events","plugins_objects", "plugins_history", "appevents"]) return pluginsState @@ -873,7 +873,7 @@ def check_and_run_user_event(db, all_plugins, pluginsState): execution_log.finalize_event("run") elif event == 'update_api': # async handling - update_api(db, all_plugins, False, param.split(','), True) + update_api(db, all_plugins, param.split(','), True) else: mylog('minimal', ['[check_and_run_user_event] WARNING: Unhandled event in execution queue: ', event, ' | ', param])