Changeset: 0c61a0ebc2b9 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0c61a0ebc2b9
Modified Files:
        clients/iotapi/documentation/websockets_api.rst
        clients/iotapi/src/Streams/streams.py
        clients/iotapi/src/Streams/streamscontext.py
        clients/iotapi/src/WebSockets/websockets.py
Branch: iot
Log Message:

Finished first version of documentation for web api. Added pattern for response 
messages during a WebSocket session.


diffs (truncated from 401 to 300 lines):

diff --git a/clients/iotapi/documentation/websockets_api.rst 
b/clients/iotapi/documentation/websockets_api.rst
--- a/clients/iotapi/documentation/websockets_api.rst
+++ b/clients/iotapi/documentation/websockets_api.rst
@@ -18,7 +18,7 @@ The following sections explain the avail
 sub
 ---
 
-Subscribes for new basket creations from a specific stream. Whenever a basket 
is created, the server sends a notification message indicating the number of 
inserted tuples in the new basket. The user has to specify the stream's name 
and schema.
+Subscribes for new basket creations from a specific stream. Whenever a basket 
is created, the server sends a notification message indicating the number of 
inserted tuples in the new basket. The user has to specify the stream's name 
and schema. To subscribe to a temperature stream, the following would suffice:
 
 .. code-block:: json
 
@@ -33,6 +33,14 @@ unsub
 
 Unsubscribes a previous subscribed stream for a client. The user has to 
specify the stream's name and schema. The example is the same as above, just 
changing the request keyword.
 
+.. code-block:: json
+
+    {
+        "request": "unsub",
+        "schema": "measures",
+        "stream": "temperature"
+    }
+
 read
 ----
 
@@ -40,7 +48,7 @@ Reads output result from baskets generat
 
 .. important:: The user has not to be subscribed to the stream in order to 
read data from it!
 
-It's possible to provide an offset, a limit and a basket number where the read 
should start. The request will always provide a result, even if the query 
provides no tuples to read. The user has to specify the stream's name and 
schema.
+It's possible to provide an offset, a limit and a basket number where the read 
should start. The request will always provide a result, even if the query 
provides no tuples to read. The user has to specify the stream's name and 
schema. A possible query for the temperatures stream:
 
 .. code-block:: json
 
@@ -54,7 +62,7 @@ It's possible to provide an offset, a li
 info
 ----
 
-Retrieves information about a giving stream if a stream's name and schema are 
provided, or all the existing streams in the system otherwise.
+Retrieves information about a giving stream if a stream's name and schema are 
provided, or all the existing streams in the system otherwise. To request 
information of temperature stream:
 
 .. code-block:: json
 
@@ -66,3 +74,178 @@ Retrieves information about a giving str
 
 Responses
 =========
+
+The response messages, are also provided with JSON. They contain a 
:code:`response` field, identifying the type of the message.
+
+error
+-----
+
+An internal error occurred in the server during a client's request. The 
:code:`message` contains a string explaining the error. The following error 
message happens when the user attempts to unsubscribed to a non subscribed 
stream:
+
+.. code-block:: json
+
+    {
+        "response": "error",
+        "message": "Stream measures.temperature not present in the user's 
subscriptions!"
+    }
+
+subscribed
+----------
+
+Message confirming the subscription to new baskets notifications of a stream.
+
+.. code-block:: json
+
+    {
+        "response": "subscribed",
+        "schema": "measures",
+        "stream": "temperature"
+    }
+
+unsubscribed
+------------
+
+Message confirming the removal of a subscription to new baskets notifications 
of a stream.
+
+.. code-block:: json
+
+    {
+        "response": "unsubscribed",
+        "schema": "measures",
+        "stream": "temperature"
+    }
+
+removed
+-------
+
+If a stream is removed on MonetDB's engine, but the client is still 
subscribed, then this message is sent.
+
+.. code-block:: json
+
+    {
+        "response": "removed",
+        "schema": "measures",
+        "stream": "temperature"
+    }
+
+notification
+------------
+
+Notification of a new basket creation from a subscribed stream. The message 
contains the basket number and the number of tuples in the new basket. A 
possible notification example for the above stream:
+
+.. code-block:: json
+
+    {
+        "response": "notification",
+        "schema": "measures",
+        "stream": "temperature",
+        "basket": 2,
+        "count": 50
+    }
+
+read
+----
+
+Response message for a read query. Contains the reconstructed tuples 
listening. The tuples are listened in the say they are inserted in the RESTful 
webserver. If a column has a null value, the JSON's :code:`null` value will be 
listened. A possible query result for the above stream:
+
+.. code-block:: json
+
+    {
+        "response": "read",
+        "schema": "measures",
+        "stream": "temperature",
+        "count": 3,
+        "tuples": [
+            {
+                "sensorid": "living room",
+                "temperature": 32.6
+            },
+            {
+                "sensorid": "kitchen",
+                "temperature": 34.2
+            },
+            {
+                "sensorid": "bathroom",
+                "temperature": 28.9
+            }
+        ]
+    }
+
+info
+----
+
+Message with details about a stream including both columns and baskets 
details. Note that the possible types list are restricted to the MonetDB 
kernel.  A possible example for the above stream:
+
+.. code-block:: json
+
+    {
+        "response": "info",
+        "schema": "measures",
+        "stream": "temperature",
+        "columns": [
+            {
+                "name": "sensorid",
+                "type": "clob"
+            },
+            {
+                "name": "temperature",
+                "type": "real"
+            }
+        ],
+        "baskets_count": 3,
+        "baskets_listing": [
+            {
+                "number": 1,
+                "count": 20
+            },
+            {
+                "number": 2,
+                "count": 25
+            },
+            {
+                "number": 3,
+                "count": 12
+            }
+        ]
+    }
+
+data
+----
+
+Return a info messaging regarding all the streams in the system. An example 
with the temperatures stream:
+
+.. code-block:: json
+
+    {
+        "response": "data",
+        "streams_count": 1,
+        "streams_listing": [
+            "schema": "measures",
+            "stream": "temperature",
+            "columns": [
+                {
+                    "name": "sensorid",
+                    "type": "clob"
+                },
+                {
+                    "name": "temperature",
+                    "type": "real"
+                }
+            ],
+            "baskets_count": 3,
+            "baskets_listing": [
+                {
+                    "number": 1,
+                    "count": 20
+                },
+                {
+                    "number": 2,
+                    "count": 25
+                },
+                {
+                    "number": 3,
+                    "count": 12
+                }
+            ]
+        ]
+    }
diff --git a/clients/iotapi/src/Streams/streams.py 
b/clients/iotapi/src/Streams/streams.py
--- a/clients/iotapi/src/Streams/streams.py
+++ b/clients/iotapi/src/Streams/streams.py
@@ -31,7 +31,8 @@ class StreamBasketsHandler(FileSystemEve
         if isinstance(event, DirCreatedEvent):
             basket_string = os.path.basename(os.path.normpath(event.src_path))
             count = self._stream.append_basket(basket_string)
-            notify_stream_inserts_to_clients(self._stream.get_schema_name(), 
self._stream.get_stream_name(), count)
+            notify_stream_inserts_to_clients(self._stream.get_schema_name(), 
self._stream.get_stream_name(),
+                                             int(basket_string), count)
 
     def on_deleted(self, event):
         if isinstance(event, DirDeletedEvent):
@@ -65,10 +66,11 @@ class IOTStream(object):
         dic = OrderedDict({'schema': self._schema_name, 'stream': 
self._stream_name,
                            'columns': [value.to_json_representation() for 
value in self._columns.values()]})
         self._baskets_lock.acquire_read()
-        baskets = {'count': len(self._baskets),
-                   'details': [{'number': k, 'total': v} for k, v in 
self._baskets.items()]}
+        count = len(self._baskets)
+        listing = [{'number': k, 'count': v} for k, v in self._baskets.items()]
         self._baskets_lock.release()
-        dic['baskets'] = baskets
+        dic['baskets_count'] = count
+        dic['baskets_listing'] = listing
         return dic
 
     def append_basket(self, path):
@@ -142,4 +144,4 @@ class IOTStream(object):
 
         keys = results.keys()  # TODO check if this is viable for many tuples!!
         tuples = [dict(zip(keys, values)) for values in zip(*(results[k] for k 
in keys))]
-        return {'total': read_tuples, 'tuples': tuples}
+        return {'schema': self._schema_name, 'stream': self._stream_name, 
'count': read_tuples, 'tuples': tuples}
diff --git a/clients/iotapi/src/Streams/streamscontext.py 
b/clients/iotapi/src/Streams/streamscontext.py
--- a/clients/iotapi/src/Streams/streamscontext.py
+++ b/clients/iotapi/src/Streams/streamscontext.py
@@ -39,8 +39,8 @@ class IOTStreams(object):
 
     def get_streams_data(self):
         self._locker.acquire_read()
-        res = {'count': len(self._context),
-               'details': [value.get_data_dictionary() for value in 
self._context.values()]}
+        res = {'streams_count': len(self._context),
+               'streams_listing': [value.get_data_dictionary() for value in 
self._context.values()]}
         self._locker.release()
         return res
 
diff --git a/clients/iotapi/src/WebSockets/websockets.py 
b/clients/iotapi/src/WebSockets/websockets.py
--- a/clients/iotapi/src/WebSockets/websockets.py
+++ b/clients/iotapi/src/WebSockets/websockets.py
@@ -26,11 +26,10 @@ def unsubscribe_removed_streams(concaten
 from Streams.streamscontext import Streams_Context, IOTStreams  # avoid 
circular dependency
 
 
-def notify_stream_inserts_to_clients(schema_name, stream_name, count):
-    concatenated_name = IOTStreams.get_context_entry_name(schema_name, 
stream_name)
+def notify_stream_inserts_to_clients(schema_name, stream_name, basket_number, 
count):
     WebClientsLock.acquire_read()
     for client in WebClients:
-        client.send_notification_message(concatenated_name, schema_name, 
stream_name, count)
+        client.send_notification_message(schema_name, stream_name, 
basket_number, count)
     WebClientsLock.release()
 
 
@@ -43,8 +42,8 @@ class IOTAPI(WebSocket):
         self._subscriptions_locker = RWLock()
 
     def sendJSONMessage(self, response, message):  # IMPORTANT always use this 
method to send messages to clients!!!!!
-        json_message = json.dumps({'response': response, 'message': message})
-        super(IOTAPI, self).sendMessage(json_message)  # send JSON Strings to 
clients
+        message['response'] = response
+        super(IOTAPI, self).sendMessage(json.dumps(message))  # send JSON 
Strings to clients
 
     def handleConnected(self):  # overriden
         WebClientsLock.acquire_write()
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to