Handling Client Interactions#

The RESTrict Framework classifies three types of communication interactions between the client and the server.

Accessor operations#

When accessing state of the application, the server immediately responds with the state queried by the client.

digraph G {
  edge [fontname="Courier"];
  node [fontname="Courier"];
  fontname="Courier";
  nodesep=3;
  {
    rank=same;
    node [shape=box];
    actor1_top [label="Client"];
    actor2_top [label="Server"];
    edge [style = invis];
    actor1_top -> actor2_top;
  }
  {
    rank=same;
    node [shape=box];
    actor1_bottom [label="Client"];
    actor2_bottom [label="Server"];
    edge [style = invis];
    actor1_bottom -> actor2_bottom;
  }
  node [shape=point];
  edge [arrowhead=none];
  actor1_event1
  actor1_event3
  actor1_top ->
  actor1_event1 ->
  actor1_event3 ->
  actor1_bottom;
  actor2_event1
  actor2_event2
  actor2_top ->
  actor2_event1 ->
  actor2_event2 ->
  actor2_bottom;
  {rank=same; actor1_event1 actor2_event1}
  edge [constraint=false, arrowhead=normal];
  actor1_event1 -> actor2_event1 [xlabel="accessor request"];
  actor2_event2 -> actor1_event3 [xlabel="immediate response"];
}

Fig. 11 Accessor operations result in synchronous responses#

State modification subscriptions#

The client can subscribe to state changes of resources. This creates a duplex communication channel to receive state changes through the connection, as well as unsubscribe from state change syndication.

digraph G {
  edge [fontname="Courier"];
  node [fontname="Courier"];
  fontname="Courier";
  nodesep=3;
  {
    rank=same;
    node [shape=box];
    actor1_top [label="Client"];
    actor2_top [label="Server"];
    edge [style = invis];
    actor1_top -> actor2_top;
  }
  {
    rank=same;
    node [shape=box];
    actor1_bottom [label="Client"];
    actor2_bottom [label="Server"];
    edge [style = invis];
    actor1_bottom -> actor2_bottom;
  }
  node [shape=point];
  edge [arrowhead=none];
  actor1_event1;
  actor1_event2;
  actor1_event3;
  actor1_event4;
  actor1_top ->
  actor1_event1 ->
  actor1_event2 ->
  actor1_event3 ->
  actor1_event4 ->
  actor1_bottom;
  actor2_event1;
  actor2_event2;
  actor2_event3;
  actor2_event4;
  actor2_top ->
  actor2_event1 ->
  actor2_event2 ->
  actor2_event3 ->
  actor2_event4 ->
  actor2_bottom;
  {rank=same; actor1_event1 actor2_event1}
  {rank=same; actor1_event2 actor2_event2}
  {rank=same; actor1_event3 actor2_event3}
  {rank=same; actor1_event4 actor2_event4}
  edge [constraint=false, arrowhead=normal];
  actor1_event1 -> actor2_event1 [xlabel="subscribe to resource changes"];
  edge [style=dashed]
  actor2_event2 -> actor1_event2 [xlabel="asynchronous state changes"];
  actor2_event3 -> actor1_event3 [xlabel="asynchronous state changes"];
  edge [style=solid];
  actor1_event4 -> actor2_event4 [xlabel="unsubscribe"];
}

Fig. 12 Client subscribes for resource modification notifications#

Mutation operations#

Clients can mutate the state of the application (of course). In doing so, the client sends the mutation request to the server. If the server has a push notification channel open to the client, then it will send the client a notification with the final state of the application in the context of the modified resource.

digraph G {
    edge [fontname="Courier"];
    node [fontname="Courier"];
    fontname="Courier";
    nodesep=3;
    {
        rank=same;
        node [shape=box];
        actor1_top [label="Client"];
        actor2_top [label="Server"];
        edge [style = invis];
        actor1_top -> actor2_top;
    }
    {
        rank=same;
        node [shape=box];
        actor1_bottom [label="Client"];
        actor2_bottom [label="Server"];
        edge [style = invis];
        actor1_bottom -> actor2_bottom;
    }
    node [shape=point];
    edge [arrowhead=none];
    actor1_event1;
    actor1_event2;
    actor1_event3;
    actor1_top ->
    actor1_event1 ->
    actor1_event2 ->
    actor1_event3 ->
    actor1_bottom;
    actor2_event1;
    actor2_event2;
    actor2_event3;
    actor2_top ->
    actor2_event1 ->
    actor2_event2 ->
    actor2_event3 ->
    actor2_bottom;
    {rank=same; actor1_event1 actor2_event1}
    {rank=same; actor1_event2 actor2_event2}
    {rank=same; actor1_event3 actor2_event3}
    edge [constraint=false, arrowhead=normal];
    actor1_event1 -> actor2_event1 [xlabel="mutation request"];
    actor2_event2 -> actor1_event2 [xlabel="request accepted"];
    edge [style=dashed]
    actor2_event3 -> actor1_event3 [xlabel="asynchronous state update"];
}

Fig. 13 Mutation operations result in asynchronous notifications#

If the server does not have a channel to send push notifications, then the client can later ask for the result of the transaction.

digraph G {
    node [fontname="Courier"];
    edge [fontname="Courier"];
    fontname="Courier";
    nodesep=1.0;
    {
        rank=same;
        node [shape=box];
        actor1_top [label="Client"];
        actor2_top [label="" shape=none];
        actor3_top [label="Server"];
        edge [style = invis];
        actor1_top -> actor2_top -> actor3_top;
    }
    {
        rank=same;
        node [shape=box];
        actor1_bottom [label="Client"];
        actor2_bottom [label="" shape=none];
        actor3_bottom [label="Server"];
        edge [style = invis];
        actor1_bottom -> actor2_bottom -> actor3_bottom;
    }
    node [shape=point];
    edge [arrowhead=none];
    actor1_event1;
    actor1_event2;
    actor1_event4;
    actor1_event5;
    actor1_top ->
    actor1_event1 ->
    actor1_event2 ->
    actor1_event4 ->
    actor1_event5 ->
    actor1_bottom;
    actor2_event3 [shape=point label="" color=none];
    actor2_top ->
    actor2_event3 ->
    actor2_bottom [color=none];
    actor3_event1;
    actor3_event2;
    actor3_event3;
    actor3_event4;
    actor3_event5;
    actor3_top ->
    actor3_event1 ->
    actor3_event2 ->
    actor3_event3 ->
    actor3_event4 ->
    actor3_event5 ->
    actor3_bottom;
    {rank=same; actor1_event1 actor3_event1}
    {rank=same; actor1_event2 actor3_event2}
    {rank=same; actor2_event3 actor3_event3}
    {rank=same; actor1_event4 actor3_event4}
    {rank=same; actor1_event5 actor3_event5}
    edge [constraint=false, arrowhead=normal];
    actor1_event1 -> actor3_event1 [xlabel="mutation request"];
    actor3_event2 -> actor1_event2 [xlabel="accepted"];
    actor3_event3 -> actor2_event3 [xlabel="return" arrowhead=dot style=dashed];
    actor1_event4 -> actor3_event4 [xlabel="state status request"]
    actor3_event5 -> actor1_event5 [xlabel="state status response"]
}

Fig. 14 Client queries for state modification when server push fails#