Merge pull request #5064 from GabrielInTheWorld/doubleHitProjector

Enhances the autoupdate of projector by change-id
This commit is contained in:
Emanuel Schütze 2019-10-02 17:00:25 +02:00 committed by GitHub
commit 50bd31a9a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 20 deletions

View File

@ -18,6 +18,21 @@ interface AllProjectorData {
[id: number]: ProjectorData | { error: string }; [id: number]: ProjectorData | { error: string };
} }
/**
* Received data from server.
*/
interface ProjectorWebsocketMessage {
/**
* The `change_id` of the current update.
*/
change_id: number;
/**
* The necessary new projector-data.
*/
data: AllProjectorData;
}
/** /**
* This service handles the websocket connection for the projector data. * This service handles the websocket connection for the projector data.
* Each projector instance registers itself by calling `getProjectorObservable`. * Each projector instance registers itself by calling `getProjectorObservable`.
@ -43,6 +58,11 @@ export class ProjectorDataService {
*/ */
private readonly updateProjectorDataDebounceSubject = new Subject<void>(); private readonly updateProjectorDataDebounceSubject = new Subject<void>();
/**
* Holds the current change id to check, if the update contains new content or a deprecated one.
*/
private currentChangeId = 0;
/** /**
* Constructor. * Constructor.
* *
@ -50,13 +70,17 @@ export class ProjectorDataService {
*/ */
public constructor(private websocketService: WebsocketService) { public constructor(private websocketService: WebsocketService) {
// Dispatch projector data. // Dispatch projector data.
this.websocketService.getOberservable('projector').subscribe((update: AllProjectorData) => { this.websocketService.getOberservable('projector').subscribe((update: ProjectorWebsocketMessage) => {
Object.keys(update).forEach(_id => { if (this.currentChangeId > update.change_id) {
return;
}
Object.keys(update.data).forEach(_id => {
const id = parseInt(_id, 10); const id = parseInt(_id, 10);
if (this.currentProjectorData[id]) { if (this.currentProjectorData[id]) {
this.currentProjectorData[id].next(update[id] as ProjectorData); this.currentProjectorData[id].next(update.data[id] as ProjectorData);
} }
}); });
this.currentChangeId = update.change_id;
}); });
// The service need to re-register, if the websocket connection was lost. // The service need to re-register, if the websocket connection was lost.

View File

@ -179,9 +179,7 @@ class ListenToProjectors(BaseWebsocketClientMessage):
for projector_id, data in projector_data.items(): for projector_id, data in projector_data.items():
consumer.projector_hash[projector_id] = hash(str(data)) consumer.projector_hash[projector_id] = hash(str(data))
await consumer.send_json( await consumer.send_projector_data(projector_data, in_response=id)
type="projector", content=projector_data, in_response=id
)
class PingPong(BaseWebsocketClientMessage): class PingPong(BaseWebsocketClientMessage):

View File

@ -217,7 +217,12 @@ def handle_changed_elements(elements: Iterable[Element]) -> None:
# Send projector # Send projector
channel_layer = get_channel_layer() channel_layer = get_channel_layer()
await channel_layer.group_send( await channel_layer.group_send(
"projector", {"type": "projector_changed", "data": projector_data} "projector",
{
"type": "projector_changed",
"data": projector_data,
"change_id": change_id,
},
) )
if elements: if elements:

View File

@ -190,6 +190,8 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
The projector has changed. The projector has changed.
""" """
all_projector_data = event["data"] all_projector_data = event["data"]
change_id = event["change_id"]
projector_data: Dict[int, Dict[str, Any]] = {} projector_data: Dict[int, Dict[str, Any]] = {}
for projector_id in self.listen_projector_ids: for projector_id in self.listen_projector_ids:
data = all_projector_data.get(projector_id, []) data = all_projector_data.get(projector_id, [])
@ -199,4 +201,19 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
self.projector_hash[projector_id] = new_hash self.projector_hash[projector_id] = new_hash
if projector_data: if projector_data:
await self.send_json(type="projector", content=projector_data) await self.send_projector_data(projector_data, change_id=change_id)
async def send_projector_data(
self,
data: Dict[int, Dict[str, Any]],
change_id: Optional[int] = None,
in_response: Optional[str] = None,
) -> None:
"""
Sends projector data to the consumer.
"""
if change_id is None:
change_id = await element_cache.get_current_change_id()
content = {"change_id": change_id, "data": data}
await self.send_json(type="projector", content=content, in_response=in_response)

View File

@ -565,12 +565,15 @@ async def test_listen_to_projector(communicator, set_config):
content = response.get("content") content = response.get("content")
assert type == "projector" assert type == "projector"
assert content == { assert content == {
"1": [ "change_id": 3,
{ "data": {
"data": {"name": "slide1", "event_name": "OpenSlides"}, "1": [
"element": {"id": 1, "name": "test/slide1"}, {
} "data": {"name": "slide1", "event_name": "OpenSlides"},
] "element": {"id": 1, "name": "test/slide1"},
}
]
},
} }
@ -595,12 +598,15 @@ async def test_update_projector(communicator, set_config):
content = response.get("content") content = response.get("content")
assert type == "projector" assert type == "projector"
assert content == { assert content == {
"1": [ "change_id": 4,
{ "data": {
"data": {"name": "slide1", "event_name": "Test Event"}, "1": [
"element": {"id": 1, "name": "test/slide1"}, {
} "data": {"name": "slide1", "event_name": "Test Event"},
] "element": {"id": 1, "name": "test/slide1"},
}
]
},
} }