Make Consumer real async again

This commit is contained in:
Oskar Hahn 2018-08-30 09:07:06 +02:00 committed by FinnStutzenstein
parent 8adaa6118a
commit 732de97ec2
6 changed files with 93 additions and 26 deletions

View File

@ -4,6 +4,7 @@ from typing import Any, Dict, List
from django.apps import AppConfig from django.apps import AppConfig
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db.models.signals import post_migrate from django.db.models.signals import post_migrate
from ..utils.projector import register_projector_elements from ..utils.projector import register_projector_elements
@ -37,6 +38,14 @@ class CoreAppConfig(AppConfig):
ProjectorViewSet, ProjectorViewSet,
TagViewSet, TagViewSet,
) )
from ..utils.constants import set_constants, get_constants_from_apps
# Set constants
try:
set_constants(get_constants_from_apps())
except ImproperlyConfigured:
# Database is not loaded. This happens in tests.
pass
# Define config variables and projector elements. # Define config variables and projector elements.
config.update_config_variables(get_config_variables()) config.update_config_variables(get_config_variables())

View File

@ -48,6 +48,7 @@ from .models import (
ProjectorMessage, ProjectorMessage,
Tag, Tag,
) )
from ..utils.constants import get_constants
# Special Django views # Special Django views
@ -133,15 +134,7 @@ class WebclientJavaScriptView(utils_views.View):
# angular constants # angular constants
angular_constants = '' angular_constants = ''
for app in apps.get_app_configs(): for key, value in get_constants().items():
try:
# Each app can deliver values to angular when implementing this method.
# It should return a list with dicts containing the 'name' and 'value'.
get_angular_constants = app.get_angular_constants
except AttributeError:
# The app doesn't have this method. Continue to next app.
continue
for key, value in get_angular_constants().items():
value = json.dumps(value) value = json.dumps(value)
angular_constants += ".constant('{}', {})".format(key, value) angular_constants += ".constant('{}', {})".format(key, value)

View File

@ -0,0 +1,40 @@
from typing import Any, Dict
from django.apps import apps
def get_constants_from_apps() -> Dict[str, Any]:
out: Dict[str, Any] = {}
for app in apps.get_app_configs():
try:
# Each app can deliver values to angular when implementing this method.
# It should return a list with dicts containing the 'name' and 'value'.
get_angular_constants = app.get_angular_constants
except AttributeError:
# The app doesn't have this method. Continue to next app.
continue
out.update(get_angular_constants())
return out
constants = None
def get_constants() -> Dict[str, Any]:
"""
Returns the constants.
This method only returns a static dict, so it is fast and can be used in a
async context.
"""
if constants is None:
raise RuntimeError("Constants are not set.")
return constants
def set_constants(value: Dict[str, Any]) -> None:
"""
Sets the constants variable.
"""
global constants
constants = value

View File

@ -4,7 +4,6 @@ import jsonschema
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from channels.db import database_sync_to_async from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer from channels.generic.websocket import AsyncJsonWebsocketConsumer
from django.apps import apps
from ..core.config import config from ..core.config import config
from ..core.models import Projector from ..core.models import Projector
@ -16,6 +15,7 @@ from .collection import (
format_for_autoupdate, format_for_autoupdate,
from_channel_message, from_channel_message,
) )
from .constants import get_constants
class ProtocollAsyncJsonWebsocketConsumer(AsyncJsonWebsocketConsumer): class ProtocollAsyncJsonWebsocketConsumer(AsyncJsonWebsocketConsumer):
@ -31,7 +31,7 @@ class ProtocollAsyncJsonWebsocketConsumer(AsyncJsonWebsocketConsumer):
"type": { "type": {
"description": "Defines what kind of packages is packed.", "description": "Defines what kind of packages is packed.",
"type": "string", "type": "string",
"pattern": "notify|constantsRequest", # The server can sent other types "pattern": "notify|constants", # The server can sent other types
}, },
"content": { "content": {
"description": "The content of the package.", "description": "The content of the package.",
@ -137,19 +137,10 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
) )
else: else:
await self.send_json(type='error', content='Invalid notify message', in_response=id) await self.send_json(type='error', content='Invalid notify message', in_response=id)
elif type == 'constantsRequest':
angular_constants: Dict[str, Any] = {} elif type == 'constants':
for app in apps.get_app_configs(): # Return all constants to the client.
try: await self.send_json(type='constants', content=get_constants(), in_response=id)
# Each app can deliver values to angular when implementing this method.
# It should return a list with dicts containing the 'name' and 'value'.
get_angular_constants = app.get_angular_constants
except AttributeError:
# The app doesn't have this method. Continue to next app.
continue
constants = await database_sync_to_async(get_angular_constants)()
angular_constants.update(constants)
await self.send_json(type='constantsResponse', content=angular_constants, in_response=id)
async def send_notify(self, event: Dict[str, Any]) -> None: async def send_notify(self, event: Dict[str, Any]) -> None:
""" """

View File

@ -1,4 +1,6 @@
import pytest
from django.test import TestCase, TransactionTestCase from django.test import TestCase, TransactionTestCase
from pytest_django.django_compat import is_django_unittest
from pytest_django.plugin import validate_django_db from pytest_django.plugin import validate_django_db
@ -38,3 +40,20 @@ def pytest_collection_modifyitems(items):
return 0 return 0
items.sort(key=weight_test_case) items.sort(key=weight_test_case)
@pytest.fixture(autouse=True)
def constants(request):
"""
Resets the constants on every test.
Uses fake constants, if the db is not in use.
"""
from openslides.utils.constants import set_constants, get_constants_from_apps
if 'django_db' in request.node.keywords or is_django_unittest(request):
# When the db is created, use the original constants
set_constants(get_constants_from_apps())
else:
# Else: Use fake constants
set_constants({'constant1': 'value1', 'constant2': 'value2'})

View File

@ -241,3 +241,18 @@ async def test_send_unknown_type(communicator):
response = await communicator.receive_json_from() response = await communicator.receive_json_from()
assert response['type'] == 'error' assert response['type'] == 'error'
assert response['in_response'] == 'test_id' assert response['in_response'] == 'test_id'
@pytest.mark.asyncio
async def test_request_constants(communicator, settings):
await set_config('general_system_enable_anonymous', True)
await communicator.connect()
# Await the startup data
await communicator.receive_json_from()
await communicator.send_json_to({'type': 'constants', 'content': '', 'id': 'test_id'})
response = await communicator.receive_json_from()
assert response['type'] == 'constants'
# See conftest.py for the content of 'content'
assert response['content'] == {'constant1': 'value1', 'constant2': 'value2'}