The Gatherer mainly focuses on gathering as much information/feedback from stakeholders as he can. This helps him build a direction for the product for a specific period of time. Although he gets new requirements, features and requests, he strives to keep the direction steady and aligns new requirements to it. Together with the team, he prioritizes the backlog consequently. This helps him ensure that the direction is clear to the team.
The Gatherer keeps a personal log for all the possible long-term features that could be implemented in the product. He notes everything down regardless of whether the come from from customers, or by comparing with other similar products in the market. As soon as one of these features is barely considered valid for implementation, adds them to the product backlog and discussed it with the team.
He insists on frequent grooming sessions; they keep everyone in the team informed and mentally prepared for the forthcoming tasks. Moreover, grooming sessions keep the backlog clean and optimised, since most of the old issues would have been already solved and need to be deleted or rephrased.
The Gatherer always tries to keep the team involved. At the regular meetings with customers, he usually summarises the notes and shares them with the team. Likewise, he tends to convey the feedback from stakeholders (positive or negative) about the development process, the quality of deliverables, and their expectation to the product and the team.
As a Product Owner, he believes in the role as responsible for defining the product path. That is of course after analysing requirements, business needs and use cases. He has established a strong relationship with the customers, based on mutual trust and sending a clear signal that he takes product ownership seriously.
This post concludes the series about different flavours of a Product Owner.
In this blog I will look at the inner workings of a Zookeeper client as of version 3.4.6, which I believe is the most commonly used version at the time of writing (even though 3.5.0 has been released – it probably works the same way anyway). Especially the exact conditions of getting ConnectionLossException and SessionExpiredException
But he diagram leaves some questions about what exactly makes those DISCONNECTED and SESSION_EXPIRED events occur?
One important thing to know about the inner workings of a ZK client is that it has two very important threads running
It is mostly the inner workings of SendThread that is interesting when we want to answer the above questions
So lets look at a very simplified pseudo-code description of how the SendThread works. Basically SendThread runs in an infinite loop until its state is set to CLOSED (explicitly indirectly by the user of the client or due to SESSION_EXPIRED event). After that the SendThread dies and the entire ZK client is useless.
The client holds a state. The state can be one of NOT_CONNECTED, CONNECTING, CONNECTED, CONNECTEDREADONLY, CLOSED or AUTH_FAILED, starting out at NOT_CONNECTED. Lets just consider CONNECTED and CONNECTEDREADONLY the same for this simplified description (Hint: Before reading the pseudo-code you may want to click “Expand code” in the top bar – will appear if you move your mouse-pointer into the code-block)
while state has not been set to CLOSED or AUTH_FAIELD
if not connected on socket layer
if (closing or state is CLOSED or state is AUTH_FAIELD) break while loop
set state to CONNECTING
connect on socket layer
send connect request to server
if too much time has passed since last received packet from server
disconnect socket layer (go into reconnecting in lines 2-7 at next loop)
all outgoing or pending requests get a ConnectionLossException
if state is CONNECTED and
more than half of read-timeout has passed since last packet was sent to server
put ping-request on outgoing queue
wait for server being ready for interaction, but not more than
half of read-timeout has passed since last packet was sent to server or
read-timeout has passed since last received packed from server (connect-timeout in case of state not CONNECTED)
if server is ready with a response read it
if it is a connect response from server
if server responded "session expired" (negotiated session-timeout is -1)
set state to CLOSED
disconnect socket layer (go into reconnecting at line 2 and leaving the loop at line 3 at next loop)
all client-requests that did not get a response (still on outgoing queue) yet will get a SessionExpiredException
else set state to CONNECTED
else if it is a response to an client-operation hand the response over to the client
else if it is a callback/watcher response tell EventThread to call the relevant callbacks/watchers
remove the corresponding request from pending queue
if server is ready to receive requests and there is a request on outgoing queue
remove it from outgoing queue
send it to server
park it on pending queue
When you use the ZK client (create znode, set-data, get-data etc) it will put a request on the outgoing queue, and wait it to finish processing (“hand the response over to the client” in SendThread pseudo-code above)
The code refers to two values
As long as you are not connected the session-timeout used for the above calculations is the value you give when constructing your ZK client. After connection it is the session-timeout the client negotiated with the server
Lets look at details on one of the statements in the pseudo-code above
too much time has passed since last received packet from server =
state is CONNECTED and time since last received packet from server is more than read-timeout, or
state is not CONNECTED and time since last received packet from server is more than connect-timeout
Now we are ready to answer the questions
If you, as a user of the client, are not doing any interaction with the server yourself, SendThread will try do a ping/heartbeat request when half of read-timeout has passed, just to keep session alive.
Please note that the client single handedly decides if a DISCONNECTED event is going to occur, but that the client never decides that a SESSION_EXPIRED event is going to occur without being told by the server. Hence you will never get a SESSION_EXPIRED while the client is not able to talk to the server.
Also please note about terminology. The diagram mentions queued and pending requests. The pseudo-code mentions outgoing and pending queue/requests. Just to clarify
For consistency you could claim that the diagram ought to say
How to interpret the exceptions
When you, as the client user, get a ConnectionLossException, you do not know if the operation was actually carried out on the server or not. But the client itself might know for sure that it was not, but is not telling it in the exception. If the request is still on outgoing queue it has definitely not been carried out on the server. It is a shame that this information is not put forward to the client – e.g. introducing ConnectionLossReqNotPerformedException and ConnectionLossReqMaybePerformedException
Why does the exceptions every occur
Since the client will keep the connection alive for you, by sending ping/heartbeat in good time before read-timeout, how come you ever get into situations where those events/exceptions actually occur? You will of course see the exceptions in case of actual network problems, but they also occur if the environment in which the client/server runs is too busy and thus not giving enough execution time for the client/server to do its job in time – e.g.