Enhances the autoupdate of projector by change-id

This commit is contained in:
GabrielMeyer 2019-10-01 15:36:59 +02:00
parent aab7a41efd
commit c8d02788dc
5 changed files with 70 additions and 20 deletions

View File

@ -18,6 +18,21 @@ interface AllProjectorData {
[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.
* Each projector instance registers itself by calling `getProjectorObservable`.
@ -43,6 +58,11 @@ export class ProjectorDataService {
*/
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.
*
@ -50,13 +70,17 @@ export class ProjectorDataService {
*/
public constructor(private websocketService: WebsocketService) {
// Dispatch projector data.
this.websocketService.getOberservable('projector').subscribe((update: AllProjectorData) => {
Object.keys(update).forEach(_id => {
this.websocketService.getOberservable('projector').subscribe((update: ProjectorWebsocketMessage) => {
if (this.currentChangeId > update.change_id) {
return;
}
Object.keys(update.data).forEach(_id => {
const id = parseInt(_id, 10);
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.

View File

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

View File

@ -217,7 +217,12 @@ def handle_changed_elements(elements: Iterable[Element]) -> None:
# Send projector
channel_layer = get_channel_layer()
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:

View File

@ -190,6 +190,8 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
The projector has changed.
"""
all_projector_data = event["data"]
change_id = event["change_id"]
projector_data: Dict[int, Dict[str, Any]] = {}
for projector_id in self.listen_projector_ids:
data = all_projector_data.get(projector_id, [])
@ -199,4 +201,19 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
self.projector_hash[projector_id] = new_hash
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")
assert type == "projector"
assert content == {
"change_id": 3,
"data": {
"1": [
{
"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")
assert type == "projector"
assert content == {
"change_id": 4,
"data": {
"1": [
{
"data": {"name": "slide1", "event_name": "Test Event"},
"element": {"id": 1, "name": "test/slide1"},
}
]
},
}