def get_flag_by_field( name: str, value: Union[str, int], current_round: int, ) -> Optional[models.Flag]: """ Get flag by generic field. :param name: field name to ask cache for :param value: value of the field "field_name" to filter on :param current_round: current round :returns: Flag model instance with flag.field_name == field_value or None """ cached_key = CacheKeys.flags_cached() with utils.redis_pipeline(transaction=True) as pipe: cached, = pipe.exists(cached_key).execute() if not cached: cache_helper( pipeline=pipe, cache_key=cached_key, cache_func=caching.cache_last_flags, cache_args=(current_round, pipe), ) flag_json, = pipe.get(CacheKeys.flag_by_field(name, value)).execute() if not flag_json: return None flag = models.Flag.from_json(flag_json) return flag
def cache_last_flags(current_round: int, pipe: Pipeline) -> None: """ Cache all generated flags from last "flag_lifetime" rounds. Just adds commands to pipeline stack, don't forget to execute afterwards. :param current_round: current round :param pipe: redis connection to add command to """ game_config = game.get_current_game_config() expires = game_config.flag_lifetime * game_config.round_time * 2 with utils.db_cursor(dict_cursor=True) as (_, curs): curs.execute( _SELECT_ALL_LAST_FLAGS_QUERY, {'round': current_round - game_config.flag_lifetime}, ) flags = curs.fetchall() flag_models = list(models.Flag.from_dict(data) for data in flags) pipe.set(CacheKeys.flags_cached(), 1) for flag in flag_models: pipe.set(CacheKeys.flag_by_id(flag.id), flag.to_json(), ex=expires) pipe.set(CacheKeys.flag_by_str(flag.flag), flag.to_json(), ex=expires)