Ok I get it :)
(I know this is not defined like this in the spec, but
should it be simpler to precise ETag on GET (block2) ? This
way server may be able to return the right block or just
said I don't have this block anymore)
That does not
really help. REST enables the server to be simple. This is
what we want to exploit, and hence put the servers on the
small devices (which are sensors and actuators, and hence
naturally the origin of data). Thus, the client should not
attempt to burden the server by asking for specific
representations.
This shows, that we need more
information than just the initial request in the shared
persistence store. We need the Exchange object as usual, and
actually extend it with the ETag information to have this
feature.
Sharing the whole Exchange object does
not make sense. (see how many complex attributes there is in
this class)
We should determine which attributes we need to share.
We currently share the request, the correlationContext. This
conversation show that we will surely need the ETag
information too.
About blockwise status, I think we should not shared it
between instance, we should keep it in memory. (We don't need to handle cross instance
blockwised transfer)
As I said, I do
not care how you implement the shared ObservationStore.
Optimize the hell out of it! :D
It simply must
store all the information necessary to run the protocol
correctly.
It is indeed missing in 1.0.x and must
be added for correct behavior. (We cannot do anything if a
server does not include an ETag, but sends out notifications
faster than all blocks can be retrieved.)
My current PR doesn't handle this
correctly but if this is not implemented in 1.0.x, I think
this should be part of another PR than the clustering one ?
I would like to limit the scope of the PR or I'm afraid we
never integrate it :/
Yes, sure. This
work simply triggered a lot of concerns that should be
answered. Yet of course the changes should be done
incrementally through nicely packaged pull requests.
My recommendation for the
implementation is to have the ObservationStore Interface,
with the local hashmap class and the shared persistence
store class as described in my other mail.
(not sure to see which mail you talked
about)
Copied: “I
agreed on the separate ObservationStore. I understood that
it will have an interface, so it can be backed by a local
implementation similar to the hashmaps we already have. In
cluster mode, it is backed by a class that connects to an
external shared persistence store, so each node can be made
aware of existing Observe relationships. I don't care if
this class creates an Exchange object every time or actually
persists the original. The Exchange object returned through
the interface must simply have all the information necessary
to process the incoming message locally. As long you do not
remove the entry from the shared persistence store, I don't
see the Exchange as completed, but it will not be in the
local hashmaps anyway. We will not need it in the
Deduplicator either, if you have a NotificationOrderer
further up...”
Whoever decided to observe something,
must let one node do the registration, but also make sure
the information is put into the shared persistence store
(maybe by the node doing the registration). Once this
decision maker decides to cancel, it must remove the
information from the shared persistence store. Then, any
node will reject the next notification. Additionally, one
node could be tasked with a proactive cancellation.
This is what I tried to implement in the
current PR.
(The tests we did in Leshan seems to show that this works)
https://github.com/eclipse/leshan/pull/113
Okay. This is
still a bit clouded for me, since I do not understand the
idea behind the NotificationListeners.
Then, the initial response as well as
all notification must go to the same handler. This should
not be different from a regular response handler.
Currently the initial response is not
accessible through the notificationListener but I can change
it.
Even if I'm not totally convinced that was a good idea ...
The spec clearly made the difference between the
registration and notification (https://tools.ietf.org/html/rfc7641#section-1.2)
The central decision maker must be
informed when the initial response does not contain the
Observe option; it then needs to fall back to polling and
task a node with it.
This reinforce that the initial response
and the notifications should not be handle in a same way.
You must be
prepared to receive a response without Observe option at any
time. The “usual” case is when you receive an error message.
The initiative is with the client to ensure it gets the
representations it wants.
Anyway, this is pretty much what it is currently implemented
in the PR. MessageObserve allow to get the initial response
and so knowing if the observation is ok or not and so fall
back to polling if necessary.
NotificationListerner is used to get notifications (We just
need to decide if the first response is a notification or
not)
You still did
not answer my question from previous mails and the PR
comments: what is the idea behind the list of
NotificationListeners? Does each one correspond to a node in
the cluster? How does this help?
Now the NotificationOrderer is still
missing. As noted in the other mail (or was it GitHub?),
this depends on the application. It could be a similar thing
to the ObservationStore that is synced across all nodes. Or
it could be done in the handler itself when writing to a
database (also in a synchronized fashion).
Ok, I think this should be part of
another PR too.
It should, but
you cannot ignore this for the architecture. You will need
something similar to the shared ObservationStore that
ensures node A does not process an old notification after
node B processed the newest. You also must ensure a
synchronized write to a database. And you need to make sure
this decision maker has a consistent view on the status of
the Observe relationship.
So far we used
a ConcurrentHashmap for performance reasons. Responses and
Notifications are in the same hashmap, and hence we can have
a race condition of two notifications climbing up the stack
in different stacks. The synchronization was only done for
notifications (the NotificationOrderer). Now that we have to
notification exchanges in a separate store and need to
synchronize it anyway, we could use this directly to order
the notifications (i.e., only accept the newest and let it
climb up the stack to the handler).
Now that the
ordering is solved (:P), why do we need a list of
NotificationListeners?
Does this help?
Yes it does, thanks for your time
Matthias ;).
I hope my answer show that the content of the current PR is
near of what you expect.
(I will not be available the next 3 weeks, so no surprise if
I don't answer during this period)
Okay, I hope it
is enjoying vacation :)
It would be
great if you could solve the riddle of the
NotificationListeners before you leave! ;)
Ciao
Matthias