Send all data to the client at startup

This commit is contained in:
Oskar Hahn 2017-01-14 12:29:42 +01:00 committed by FinnStutzenstein
parent 1bc35faa55
commit ebf686ef34
9 changed files with 68 additions and 5 deletions

View File

@ -95,6 +95,8 @@ Other:
- Added new caching system with support for Redis. - Added new caching system with support for Redis.
- Support https as websocket protocol (wss). - Support https as websocket protocol (wss).
- Added migration path from 2.0. - Added migration path from 2.0.
- Add an api for apps to send data when the websocket connection is established.
- Used this api for all models expect of users to send all data to the client.
Version 2.0 (2016-04-18) Version 2.0 (2016-04-18)

View File

@ -35,3 +35,7 @@ class AgendaAppConfig(AppConfig):
# Register viewsets. # Register viewsets.
router.register(self.get_model('Item').get_collection_string(), ItemViewSet) router.register(self.get_model('Item').get_collection_string(), ItemViewSet)
def get_startup_elements(self):
from ..utils.collection import Collection
return [Collection(self.get_model('Item').get_collection_string())]

View File

@ -24,3 +24,7 @@ class AssignmentsAppConfig(AppConfig):
# Register viewsets. # Register viewsets.
router.register(self.get_model('Assignment').get_collection_string(), AssignmentViewSet) router.register(self.get_model('Assignment').get_collection_string(), AssignmentViewSet)
router.register('assignments/poll', AssignmentPollViewSet) router.register('assignments/poll', AssignmentPollViewSet)
def get_startup_elements(self):
from ..utils.collection import Collection
return [Collection(self.get_model('Assignment').get_collection_string())]

View File

@ -14,10 +14,10 @@ class CoreAppConfig(AppConfig):
# Import all required stuff. # Import all required stuff.
from django.db.models import signals from django.db.models import signals
from openslides.core.config import config from .config import config
from openslides.core.signals import post_permission_creation from .signals import post_permission_creation
from openslides.utils.rest_api import router from ..utils.rest_api import router
from openslides.utils.search import index_add_instance, index_del_instance from ..utils.search import index_add_instance, index_del_instance
from .config_variables import get_config_variables from .config_variables import get_config_variables
from .signals import delete_django_app_permissions from .signals import delete_django_app_permissions
from .views import ( from .views import (
@ -55,3 +55,10 @@ class CoreAppConfig(AppConfig):
signals.m2m_changed.connect( signals.m2m_changed.connect(
index_add_instance, index_add_instance,
dispatch_uid='m2m_index_add_instance') dispatch_uid='m2m_index_add_instance')
def get_startup_elements(self):
from .config import config
from ..utils.collection import Collection
for model in ('Projector', 'ChatMessage', 'Tag', 'ProjectorMessage', 'Countdown'):
yield Collection(self.get_model(model).get_collection_string())
yield Collection(config.get_collection_string())

View File

@ -18,3 +18,7 @@ class MediafilesAppConfig(AppConfig):
# Register viewsets. # Register viewsets.
router.register(self.get_model('Mediafile').get_collection_string(), MediafileViewSet) router.register(self.get_model('Mediafile').get_collection_string(), MediafileViewSet)
def get_startup_elements(self):
from ..utils.collection import Collection
return [Collection(self.get_model('Mediafile').get_collection_string())]

View File

@ -34,3 +34,8 @@ class MotionsAppConfig(AppConfig):
router.register(self.get_model('MotionChangeRecommendation').get_collection_string(), router.register(self.get_model('MotionChangeRecommendation').get_collection_string(),
MotionChangeRecommendationViewSet) MotionChangeRecommendationViewSet)
router.register('motions/motionpoll', MotionPollViewSet) router.register('motions/motionpoll', MotionPollViewSet)
def get_startup_elements(self):
from ..utils.collection import Collection
for model in ('Category', 'Motion', 'MotionBlock', 'Workflow', 'MotionChangeRecommendation'):
yield Collection(self.get_model(model).get_collection_string())

View File

@ -18,3 +18,7 @@ class TopicsAppConfig(AppConfig):
# Register viewsets. # Register viewsets.
router.register(self.get_model('Topic').get_collection_string(), TopicViewSet) router.register(self.get_model('Topic').get_collection_string(), TopicViewSet)
def get_startup_elements(self):
from ..utils.collection import Collection
return [Collection(self.get_model('Topic').get_collection_string())]

View File

@ -4,6 +4,7 @@ from collections import Iterable
from asgiref.inmemory import ChannelLayer from asgiref.inmemory import ChannelLayer
from channels import Channel, Group from channels import Channel, Group
from channels.auth import channel_session_user, channel_session_user_from_http from channels.auth import channel_session_user, channel_session_user_from_http
from django.apps import apps
from django.db import transaction from django.db import transaction
from ..core.config import config from ..core.config import config
@ -19,12 +20,33 @@ def ws_add_site(message):
Adds the websocket connection to a group specific to the connecting user. Adds the websocket connection to a group specific to the connecting user.
The group with the name 'user-None' stands for all anonymous users. The group with the name 'user-None' stands for all anonymous users.
Send all "starup-data" through the connection.
""" """
Group('site').add(message.reply_channel) Group('site').add(message.reply_channel)
message.channel_session['user_id'] = message.user.id message.channel_session['user_id'] = message.user.id
# Saves the reply channel to the user. Uses 0 for anonymous users. # Saves the reply channel to the user. Uses 0 for anonymous users.
websocket_user_cache.add(message.user.id or 0, message.reply_channel.name) websocket_user_cache.add(message.user.id or 0, message.reply_channel.name)
message.reply_channel.send({"accept": True})
# Collect all elements that shoud be send to the client when the websocket
# connection is established
output = []
for app in apps.get_app_configs():
try:
# Get the method get_startup_elements() from an app.
# This method has to return an iterable of Collection objects.
get_startup_elements = app.get_startup_elements
except AttributeError:
# Skip apps that do not implement get_startup_elements
continue
for collection in get_startup_elements():
output.extend(collection.as_autoupdate_for_user(message.user))
# Send all data. If there is no data, then onyl accept the connection
if output:
message.reply_channel.send({'text': json.dumps(output)})
else:
message.reply_channel.send({"accept": True})
@channel_session_user @channel_session_user

View File

@ -352,6 +352,17 @@ class Collection:
output.append(content) output.append(content)
return output return output
def as_autoupdate_for_user(self, user):
"""
Returns a list of dicts, that can be send though the websocket to a user.
"""
output = []
for collection_element in self.element_generator():
content = collection_element.as_autoupdate_for_user(user)
if content is not None:
output.append(content)
return output
def as_list_for_user(self, user): def as_list_for_user(self, user):
""" """
Returns a list of dictonaries to send them to a user, for example over Returns a list of dictonaries to send them to a user, for example over