buffet: Order device state and command updates on the server

Added strict ordering between command and state updates on the cloud
server interface. Command updates are tied to the current device state
and command update requests to the server are not dispatched until the
corresponding device state request finishes successfully.

BUG=brillo:1202
TEST=`FEATURES=test emerge-link buffet`

Change-Id: I23af95ab66b5bca91f637d9886ae234681b67104
Reviewed-on: https://chromium-review.googlesource.com/282261
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/states/state_change_queue_interface.h b/buffet/states/state_change_queue_interface.h
index 7c67829..2f11e6b 100644
--- a/buffet/states/state_change_queue_interface.h
+++ b/buffet/states/state_change_queue_interface.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include <base/callback_list.h>
 #include <base/time/time.h>
 #include <chromeos/variant_dictionary.h>
 
@@ -30,6 +31,8 @@
 class StateChangeQueueInterface {
  public:
   using UpdateID = uint64_t;
+  using Token =
+      std::unique_ptr<base::CallbackList<void(UpdateID)>::Subscription>;
 
   // Returns true if the state change notification queue is empty.
   virtual bool IsEmpty() const = 0;
@@ -46,6 +49,16 @@
   // invocation increments this value by 1.
   virtual UpdateID GetLastStateChangeId() const = 0;
 
+  // Subscribes for device state update notifications from cloud server.
+  // The |callback| will be called every time a state patch with given ID is
+  // successfully received and processed by GCD server.
+  // Returns a subscription token. As soon as this token is destroyed, the
+  // respective callback is removed from the callback list.
+  virtual Token AddOnStateUpdatedCallback(
+      const base::Callback<void(UpdateID)>& callback) WARN_UNUSED_RESULT = 0;
+
+  virtual void NotifyStateUpdatedOnServer(UpdateID update_id) = 0;
+
  protected:
   // No one should attempt do destroy the queue through the interface.
   virtual ~StateChangeQueueInterface() {}