Enhances the autoupdate of projector by change-id
This commit is contained in:
parent
aab7a41efd
commit
c8d02788dc
@ -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.
|
||||||
|
@ -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):
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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"},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user