Replace a queued downlink

Viewed 60

Some devices only have a single kind of downlink message with all parameters in it. In this case, enqueuing two downlinks is useless since latest wanted downlink can replace previous enqueued downlink(s).

This can currently be achived using gRPC DeviceService FlushQueue then Enqueue calls, with maybe the minor concurrency risk of having the downlink queue empty between the two (which may postpone the sending of the downlink is the two calls occurs at the time the downlink was to be posted).

Some other devices features a few downlink message kinds, but still several consecutive queued messages of a given kind may be useless if such message kind simply contain a full set of parameters. In this case, since the downlink queue may contain other messages two, it would be interesting to replace latest queued message if it is of the same kind of the one being queued.

Of course, ChirpStack can not magically decide and handle this on its own. But I wonder if a new "ReplaceOrEnqueue(uuid-to-replace, downlink-message)" DeviceService API call would be helpful or if I am missing a point. In my spirit, such new API call would:

  • see if uuid-to-replace can be replaced or not (still in queue or not, pending or not, in the bottom of the queue or not if those are important criteria)
  • either replace designated queued message with the new one or let it as is and enqeue the new one
2 Answers

Would it be an idea to extend the Enqueue method with a field indicating if the queue must be flushed before enqueue?

https://github.com/chirpstack/chirpstack/blob/v4.14.1/api/proto/api/device.proto#L579

Then:

message EnqueueDeviceQueueItemRequest { DeviceQueueItem queue_item = 1; }

Would become:

message EnqueueDeviceQueueItemRequest {
  DeviceQueueItem queue_item = 1;

  // Flush queue before enqueueing queue_item.
  bool flush_queue = 2;
}

Or in the case of a mix of message kinds, if gRPC caller identifies that latest queued message of same message kind has UUID x:

message EnqueueDeviceQueueItemRequest {
  DeviceQueueItem queue_item = 1;

  // Replace given queued message if possible, otherwise enqueue
  string can_replace_uuid = 2;
}

But both (optional flush and optional replace) can coexist to more easily handle both cases too.