def db_save_setting(parameter, value): """ Save Setting to DB. :param parameter: PARAMETER to match :param value: Value to save as Str :return: True if saved """ id_query = Settings.select().where(Settings.parameter == parameter) if not id_query.exists(): Settings.create(parameter=parameter) setting = id_query.get() setting.value = str(value) # Handle a BusyError attempting to write to Settings by retrying up to five times. n_retries = 0 max_retries = 5 while True: try: setting.save() break except BusyError as be: n_retries += 1 if n_retries > max_retries: raise be sleep_time_secs = 0.1 * n_retries time.sleep(sleep_time_secs) # Don't log at INFO level or above - these are typically written to # OPTECS_LOG_MESSAGES table, adding to database contention. logging.debug(f'Trip.save() Try#{n_retries} failed w/BusyError. " +' f'Sleeping {sleep_time_secs} seconds before retrying.') logging.debug('Save ' + parameter + ' -> ' + str(value)) return True
def test_entry_from_db_is_read(self): # Get the current entry, if any, ready to restore at conclusion select_q = Settings.select().where( Settings.parameter == self.TEST_SETTINGS_PARAMETER_NAME) orig_list = json.loads(select_q.get().value) self._logger.debug("Orig list = {}".format(orig_list)) test_value = None test_candidates = ('NSCC', 'XYZA', 'XXXX' ) # Unlikely real catch category codes for candidate_test_value in test_candidates: if candidate_test_value not in orig_list: test_value = candidate_test_value break errFmtStr = "Unexpectedly, every value in test value list ({}) was in orig. list" self.assertIsNotNone(test_value, errFmtStr.format(test_candidates)) self._logger.info("Adding {} to value field.".format(test_value)) # Add a catch category code to the db entry test_list = orig_list.copy() test_list.append(test_value) test_list_as_json = json.dumps(test_list) fr_update = Settings.update(value=test_list_as_json).where( Settings.parameter == self.TEST_SETTINGS_PARAMETER_NAME) fr_update.execute() # Test that newly instantiated class returns list with new entry. Three parts: # 1. Check that the db has the right updated list fr_query = Settings.select().where( Settings.parameter == self.TEST_SETTINGS_PARAMETER_NAME) updated_list = json.loads(fr_query.get().value) self.assertEqual(test_list, updated_list) self._logger.debug("updated_list = {}".format(test_list)) self.assertIsNotNone(updated_list) # 2. Verify that the pre-existing frequent catch category code does NOT get updated value - # that it doesn't do a re-pull from the db on every get of its property self.assertNotIn(test_value, self.tfcc.catch_category_codes) # 3. Instantiate a new copy of frequent catch_category_codes and verify it DOES have the # new value in the list. newtfcc = TrawlFrequentCatchCategories( self.TEST_SETTINGS_PARAMETER_NAME) self.assertIn(test_value, newtfcc.catch_category_codes)
def getset_setting(parm_name, default_val): """ Get parm_name setting from SETTINGS table. If setting not in SETTINGS, use default_val. Side-effect: also add default_val to SETTINGS table. """ fr_query = Settings.select().where(Settings.parameter == parm_name) if not fr_query.exists(): Settings.create(parameter=parm_name, value=default_val) return fr_query.get().value
def __init__(self, db): super().__init__() self._logger = logging.getLogger(__name__) self._db = db # These data will also get saved into (new) Trips cs_query = Settings.select().where(Settings.parameter == 'catch_share') if not cs_query.exists(): Settings.create(parameter='catch_share', value='TRUE') self._catchshare = cs_query.get() gt_query = Settings.select().where(Settings.parameter == 'gear_type') if not gt_query.exists(): Settings.create(parameter='gear_type', value='TRUE') self._geartype_trawl_default = gt_query.get() self._users = ObserverUsers() self._trips = ObserverTrip() self._hauls = Hauls(db=db) self._sets = Sets(db=db) self._catches = ObserverCatches(db=db) self._current_cc = None self._current_cc_name = "" # for display self._current_spec_name = "" # for display fr_query = Settings.select().where(Settings.parameter == 'first_run') if not fr_query.exists(): Settings.create(parameter='first_run', value='TRUE') self._firstrun = fr_query.get() cu_query = Settings.select().where(Settings.parameter == 'current_user') if not cu_query.exists(): Settings.create(parameter='current_user') self._current_user = cu_query.get() cu_query = Settings.select().where(Settings.parameter == 'current_user_id') if not cu_query.exists(): Settings.create(parameter='current_user_id') self._current_user_id = cu_query.get() # Type max depth as integer self._trawl_max_depth_fathoms = int(self.getset_setting( 'trawl_max_depth_fathoms', DefaultDefaultSettings.trawl_max_depth_fathoms)) self.trawlMaxDepthFathomsChanged.emit(self._trawl_max_depth_fathoms) # Confirmation-required basket weight, typed as integer self._trawl_confirm_basket_weight_lbs = int(self.getset_setting( 'trawl_confirm_basket_weight_lbs', DefaultDefaultSettings.trawl_confirm_basket_weight_lbs)) self.trawlConfirmBasketWeightLbsChanged.emit(self._trawl_confirm_basket_weight_lbs) # Max basket weight as integer, typed as integer self._trawl_max_basket_weight_lbs = int(self.getset_setting( 'trawl_max_basket_weight_lbs', DefaultDefaultSettings.trawl_max_basket_weight_lbs)) self.trawlMaxBasketWeightLbsChanged.emit(self._trawl_max_basket_weight_lbs) # Minimum and maximum degrees latitude as integer. # No emits necessary: this value will not change during a run. self._trawl_min_latitude_degrees = int(self.getset_setting( 'trawl_minimum_latitude_degrees', DefaultDefaultSettings.trawl_minimum_latitude_degrees)) self._trawl_max_latitude_degrees = int(self.getset_setting( 'trawl_maximum_latitude_degrees', DefaultDefaultSettings.trawl_maximum_latitude_degrees)) # DB Backup Thread self._backup_thread = QThread() self._backup_worker = None self._comments_all = '' self._comments_trip = '' self._comments_haul = dict() self._db_formatted_comments_trip = '' self._db_formatted_comments_haul = dict() self.currentTripId = ObserverDBUtil.db_load_setting('trip_number') # Current Trip ID if set self.update_comments() self._catches.retainedCatchWeightChanged.connect(self.update_wm5_catch_weights) # ret. catch changes --> WM5 updates self._hauls.otcWeightChanged.connect(self.update_wm5_catch_weights) # otc changes --> WM5 updates