Browse Source

poc blsi with hapic

Bastien Sevajol 5 years ago
parent
commit
e5eb747b7a
2 changed files with 78 additions and 20 deletions
  1. 78 20
      poc.py
  2. 0 0
      pocold.py

+ 78 - 20
poc.py View File

@@ -2,40 +2,98 @@ import asyncio
2 2
 import aiohttp
3 3
 import json
4 4
 from aiohttp import web
5
+import marshmallow
6
+from hapic import async as hapic
7
+from hapic.ext.aiohttp.context import AiohttpContext
5 8
 
6 9
 
7
-async def uptime_handler(request):
8
-    resp = web.StreamResponse(
9
-        status=200,
10
-        reason='OK',
11
-        headers={
12
-            'Content-Type': 'text/csv',
13
-            'Content-Disposition': 'attachment; filename="filename.csv"',
14
-        }
15
-    )
16
-    await resp.prepare(request)
10
+class UptimeHandlerStreamItem(marshmallow.Schema):
11
+    datetime = marshmallow.fields.String(required=True)
12
+    a_bool = marshmallow.fields.Boolean(required=True)
13
+    a_float = marshmallow.fields.Number(required=True)
14
+    an_int = marshmallow.fields.Integer(required=True)
15
+    text = marshmallow.fields.String(required=True)
16
+    server = marshmallow.fields.String(required=True)
17
+    zone = marshmallow.fields.String(required=True)
18
+
19
+
20
+class LineModel(object):
21
+    def __init__(
22
+        self,
23
+        *column_values
24
+    ):
25
+        self.datetime = column_values[0]
26
+        self.a_bool = column_values[1]
27
+        self.a_float = column_values[2]
28
+        self.an_int = column_values[3]
29
+        self.text = column_values[4]
30
+        self.server = column_values[5]
31
+        self.zone = column_values[6]
32
+
33
+
34
+class AsyncGenerator:
35
+    def __init__(self, session):
36
+        self._session = session
37
+        self._url = 'http://localhost:8086/query?chunk_size=1000&chunked=true'\
38
+                    '&db=resourceAux' \
39
+                    '&q=SELECT+%2A+FROM+resource_aux'
40
+        self._buffer = []
41
+        self._buffer_iter = iter(self._buffer)
42
+
43
+    async def __aiter__(self):
44
+        response = await self._session.get(self._url)
45
+        self._stream_reader = response.content
46
+        return self
47
+
48
+    async def __anext__(self):
49
+        try:
50
+            try:
51
+                # First, send next item
52
+                return next(self._buffer_iter)
53
+            # If no more item in buffer, or not started
54
+            except StopIteration:
55
+                # Read from incoming data
56
+                line = await self._stream_reader.readline()
57
+                # If end of received lines
58
+                if not line:
59
+                    # Break the iteration
60
+                    raise StopAsyncIteration()
17 61
 
62
+            # load values from received package of incomming data
63
+            data = json.loads(line.decode('utf-8'))
64
+            values = data['results'][0]['series'][0]['values']
65
+
66
+            # Prepare new buffer
67
+            self._buffer = [LineModel(*value) for value in values]
68
+            self._buffer_iter = iter(self._buffer)
69
+
70
+            # Send an item
71
+            return next(self._buffer_iter)
72
+
73
+        except StopAsyncIteration:
74
+            await self._session.close()
75
+            raise
76
+
77
+
78
+@hapic.with_api_doc()
79
+@hapic.output_stream(item_schema=UptimeHandlerStreamItem())
80
+async def uptime_handler(request):
18 81
     try:
19
-        async with aiohttp.ClientSession(loop=loop) as session:
20
-            url = 'http://localhost:8086/query?chunk_size=1000&chunked=true&db=resourceAux&q=SELECT+%2A+FROM+resource_aux'  # nopep8
21
-            async with session.get(url) as response:
22
-                async for chunk in response.content:
23
-                    bytes_to_str = chunk.decode('utf-8')
24
-                    result = json.loads(bytes_to_str)['results'][0]['series'][0]['values']  # nopep8
25
-                    for r in result:
26
-                        await resp.write(str.encode(str(r)+'\n'))
82
+        # NOTE: This session is currently closed in AsyncGenerator code
83
+        # it should be made otherwise in real code
84
+        session = aiohttp.ClientSession(loop=loop)
85
+        return AsyncGenerator(session)
27 86
 
28 87
     except Exception as e:
29 88
         # So you can observe on disconnects and such.
30 89
         print(repr(e))
31 90
         raise
32 91
 
33
-    return resp
34
-
35 92
 
36 93
 async def build_server(loop, address, port):
37 94
     app = web.Application(loop=loop)
38 95
     app.router.add_route('GET', "/uptime", uptime_handler)
96
+    hapic.set_context(AiohttpContext(app))
39 97
 
40 98
     return await loop.create_server(app.make_handler(), address, port)
41 99
 

+ 0 - 0
pocold.py View File