def element_generator(self): """ Generator that yields all collection_elements of this collection. """ # Get all cache keys. ids = self.get_all_ids() cache_keys = [ get_single_element_cache_key(self.collection_string, id) for id in ids ] cached_full_data_dict = cache.get_many(cache_keys) # Get all ids that are missing. missing_cache_keys = set(cache_keys).difference( cached_full_data_dict.keys()) missing_ids = set( get_collection_id_from_cache_key(cache_key)[1] for cache_key in missing_cache_keys) # Generate collection elements that where in the cache. for cache_key, cached_full_data in cached_full_data_dict.items(): yield CollectionElement.from_values( *get_collection_id_from_cache_key(cache_key), full_data=cached_full_data) # Generate collection element that where not in the cache. if missing_ids: from openslides.core.config import config if self.collection_string == config.get_collection_string(): # If config elements are not in the cache, they have to be read from # the config object. for key, value in config.items(): if key in missing_ids: collection_element = CollectionElement.from_values( config.get_collection_string(), key, full_data={ 'key': key, 'value': value }) # We can not use .from_instance therefore the config value # is not saved to the cache. We have to do it manualy. collection_element.save_to_cache() yield collection_element else: model = self.get_model() try: query = model.objects.get_full_queryset() except AttributeError: query = model.objects for instance in query.filter(pk__in=missing_ids): yield CollectionElement.from_instance(instance)
def __init__(self, instance=None, deleted=False, collection_string=None, id=None, full_data=None, information=None): """ Do not use this. Use the methods from_instance() or from_values(). """ self.instance = instance self.deleted = deleted self.full_data = full_data self.information = information or {} if instance is not None: self.collection_string = instance.get_collection_string() from openslides.core.config import config if self.collection_string == config.get_collection_string(): # For config objects we do not work with the pk but with the key. self.id = instance.key else: self.id = instance.pk elif collection_string is not None and id is not None: self.collection_string = collection_string self.id = id else: raise RuntimeError( 'Invalid state. Use CollectionElement.from_instance() or ' 'CollectionElement.from_values() but not CollectionElement() ' 'directly.') if self.is_deleted(): # Delete the element from the cache, if self.is_deleted() is True: self.delete_from_cache() elif instance is not None: # If this element is created via instance and the instance is not deleted # then update the cache. self.save_to_cache()
def element_generator(self): """ Generator that yields all collection_elements of this collection. """ # Get all cache keys. ids = self.get_all_ids() cache_keys = [ get_single_element_cache_key(self.collection_string, id) for id in ids] cached_full_data_dict = cache.get_many(cache_keys) # Get all ids that are missing. missing_cache_keys = set(cache_keys).difference(cached_full_data_dict.keys()) missing_ids = set( get_collection_id_from_cache_key(cache_key)[1] for cache_key in missing_cache_keys) # Generate collection elements that where in the cache. for cache_key, cached_full_data in cached_full_data_dict.items(): yield CollectionElement.from_values( *get_collection_id_from_cache_key(cache_key), full_data=cached_full_data) # Generate collection element that where not in the cache. if missing_ids: from openslides.core.config import config if self.collection_string == config.get_collection_string(): # If config elements are not in the cache, they have to be read from # the config object. for key, value in config.items(): if key in missing_ids: collection_element = CollectionElement.from_values( config.get_collection_string(), key, full_data={'key': key, 'value': value}) # We can not use .from_instance therefore the config value # is not saved to the cache. We have to do it manualy. collection_element.save_to_cache() yield collection_element else: model = self.get_model() try: query = model.objects.get_full_queryset() except AttributeError: query = model.objects for instance in query.filter(pk__in=missing_ids): yield CollectionElement.from_instance(instance)
async def set_config(key, value): """ Set a config variable in the element_cache without hitting the database. """ collection_string = config.get_collection_string() config_id = config.key_to_id[key] # type: ignore full_data = {'id': config_id, 'key': key, 'value': value} await sync_to_async(inform_changed_elements)([ Element(id=config_id, collection_string=collection_string, full_data=full_data)])
def get_all_ids(self): """ Returns a set of all ids of instances in this collection. """ from openslides.core.config import config if self.collection_string == config.get_collection_string(): ids = config.config_variables.keys() elif use_redis_cache(): ids = self.get_all_ids_redis() else: ids = self.get_all_ids_other() return ids
async def _set_config(key, value): with patch("openslides.utils.autoupdate.save_history"): collection_string = config.get_collection_string() config_id = config.key_to_id[key] # type: ignore full_data = {"id": config_id, "key": key, "value": value} await sync_to_async(inform_changed_elements)([ Element( id=config_id, collection_string=collection_string, full_data=full_data, disable_history=True, ) ])
async def set_config(key, value): """ Set a config variable in the element_cache without hitting the database. """ collection_string = config.get_collection_string() config_id = config.key_to_id[key] # type: ignore full_data = {'id': config_id, 'key': key, 'value': value} await element_cache.change_elements( {get_element_id(collection_string, config_id): full_data}) await sync_to_async(inform_data_collection_element_list)([ CollectionElement.from_values(collection_string, config_id, full_data=full_data) ])
async def test_skipping_autoupdate(set_config, get_communicator): cookie_header = await create_user_session_cookie(1) communicator = get_communicator(headers=[cookie_header]) await communicator.connect() with patch("openslides.utils.autoupdate.save_history"): await sync_to_async(inform_elements)([ AutoupdateElement( id=2, collection_string=PersonalizedCollection(). get_collection_string(), full_data={ "id": 2, "value": "new value 1", "user_id": 2 }, disable_history=True, ) ]) await sync_to_async(inform_elements)([ AutoupdateElement( id=2, collection_string=PersonalizedCollection(). get_collection_string(), full_data={ "id": 2, "value": "new value 2", "user_id": 2 }, disable_history=True, ) ]) assert await communicator.receive_nothing() # Trigger autoupdate await set_config("general_event_name", "Test Event") response = await communicator.receive_json_from() content = response["content"] assert PersonalizedCollection().get_collection_string( ) not in content["deleted"] assert PersonalizedCollection().get_collection_string( ) not in content["changed"] assert config.get_collection_string() in content["changed"] assert (content["to_change_id"] - content["from_change_id"]) == 2 # Skipped two autoupdates
def __init__(self, instance=None, deleted=False, collection_string=None, id=None, full_data=None, information=None): """ Do not use this. Use the methods from_instance() or from_values(). """ self.instance = instance self.deleted = deleted self.full_data = full_data self.information = information or {} if instance is not None: # Collection element is created via instance self.collection_string = instance.get_collection_string() from openslides.core.config import config if self.collection_string == config.get_collection_string(): # For config objects we do not work with the pk but with the key. self.id = instance.key else: self.id = instance.pk elif collection_string is not None and id is not None: # Collection element is created via values self.collection_string = collection_string self.id = id else: raise RuntimeError( 'Invalid state. Use CollectionElement.from_instance() or ' 'CollectionElement.from_values() but not CollectionElement() ' 'directly.') if self.is_deleted(): # Delete the element from the cache, if self.is_deleted() is True: self.delete_from_cache() else: # The call to get_full_data() has some sideeffects. When the object # was created with from_instance() or the object is not in the cache # then get_full_data() will save the object into the cache. # This will also raise a DoesNotExist error, if the object does # neither exist in the cache nor in the database. self.get_full_data()
def get_instance(self): """ Returns the instance as django object. May raise a DoesNotExist exception. """ if self.is_deleted(): raise RuntimeError("The collection element is deleted.") if self.instance is None: # The config instance has to be get from the config element, because # some config values are not in the db. from openslides.core.config import config if self.collection_string == config.get_collection_string(): self.instance = {'key': self.id, 'value': config[self.id]} else: model = self.get_model() try: query = model.objects.get_full_queryset() except AttributeError: query = model.objects self.instance = query.get(pk=self.id) return self.instance
def get_collection_string(self) -> str: return config.get_collection_string()