pedroferreira commited on
Commit
1862b79
·
1 Parent(s): 0fd47f9

updates streamer and stream manager

Browse files
validators/sn1_validator_wrapper.py CHANGED
@@ -48,17 +48,12 @@ class S1ValidatorAPI(ValidatorAPI):
48
  deserialize=False,
49
  streaming=True,
50
  )
51
- # uid_stream_dict = dict(zip(uids, streams_responses))
52
- # random_uid, random_stream = random.choice(list(uid_stream_dict.items()))
53
 
54
  # Creates a streamer from the selected stream
55
  stream_manager = StreamManager()
56
- await stream_manager.process_streams(params.request, streams_responses, uids)
57
 
58
- # response = await streamer.stream(params.request)
59
- # return response
60
-
61
- return None
62
 
63
 
64
  async def query_validator(self, params: QueryValidatorParams) -> Response:
 
48
  deserialize=False,
49
  streaming=True,
50
  )
 
 
51
 
52
  # Creates a streamer from the selected stream
53
  stream_manager = StreamManager()
54
+ selected_stream = await stream_manager.process_streams(params.request, streams_responses, uids)
55
 
56
+ return selected_stream
 
 
 
57
 
58
 
59
  async def query_validator(self, params: QueryValidatorParams) -> Response:
validators/stream_manager.py CHANGED
@@ -1,32 +1,28 @@
1
  import asyncio
 
2
  from .streamer import AsyncResponseDataStreamer
 
3
  from typing import List, AsyncIterator
4
  from aiohttp.web import Request
5
 
 
6
  class StreamManager:
7
-
8
- def __init__(self):
9
- ...
10
-
11
-
12
 
13
  async def process_streams(self, request:Request, streams_responses: List[AsyncIterator], stream_uids: List[int]):
14
-
15
- # create local lock for returning responses to the front-end
16
- # creates n number of streamers
17
- # organizes responses
18
- # logs responses locally
19
- # returns selected response to the front-end
20
-
21
  lock = asyncio.Lock()
22
 
23
  streamers = [AsyncResponseDataStreamer(async_iterator=stream, selected_uid=stream_uid, lock=lock) for stream, stream_uid in zip(streams_responses, stream_uids)]
24
  completed_streams = await asyncio.gather(*[streamer.stream(request) for streamer in streamers])
25
 
26
  lock.release()
27
- print(f"Stream {stream_uids} completed the operation.")
28
 
29
-
30
-
31
-
32
 
 
 
 
 
 
 
 
1
  import asyncio
2
+ import bittensor as bt
3
  from .streamer import AsyncResponseDataStreamer
4
+ from .database import LogDatabase
5
  from typing import List, AsyncIterator
6
  from aiohttp.web import Request
7
 
8
+
9
  class StreamManager:
10
+ def __init__(self, log_database_path: str = "requests_db.jsonl"):
11
+ self.log_database = LogDatabase(log_database_path)
 
 
 
12
 
13
  async def process_streams(self, request:Request, streams_responses: List[AsyncIterator], stream_uids: List[int]):
 
 
 
 
 
 
 
14
  lock = asyncio.Lock()
15
 
16
  streamers = [AsyncResponseDataStreamer(async_iterator=stream, selected_uid=stream_uid, lock=lock) for stream, stream_uid in zip(streams_responses, stream_uids)]
17
  completed_streams = await asyncio.gather(*[streamer.stream(request) for streamer in streamers])
18
 
19
  lock.release()
20
+ bt.logging.info(f"Streams from uids: {stream_uids} processing completed.")
21
 
 
 
 
22
 
23
+ await self.log_database.add_streams_to_db(completed_streams)
24
+ # Gets the first stream that acquired the lock, meaning the first stream that was able to return a non-empty chunk
25
+ _, selected_stream = next(((streamer, completed_stream) for streamer, completed_stream in zip(streamers, completed_streams) if streamer.lock_acquired), None)
26
+
27
+ return selected_stream
28
+
validators/streamer.py CHANGED
@@ -34,6 +34,7 @@ class StreamError(BaseModel):
34
  data = json.dumps(self.dict(), indent=4)
35
  return data.encode(encoding)
36
 
 
37
 
38
  class AsyncResponseDataStreamer:
39
  def __init__(self, async_iterator: AsyncIterator, selected_uid:int, lock: asyncio.Lock, delay: float = 0.1):
@@ -76,8 +77,7 @@ class AsyncResponseDataStreamer:
76
  return initiated_response
77
 
78
 
79
-
80
- async def stream(self, request: web.Request) -> web_response.StreamResponse:
81
  # response = web_response.StreamResponse(status=200, reason="OK")
82
  # response.headers["Content-Type"] = "application/json"
83
  # await response.prepare(request) # Prepare and send the headers
@@ -85,7 +85,7 @@ class AsyncResponseDataStreamer:
85
  try:
86
  start_time = time.time()
87
  client_response: web.Response = None
88
- final_response: Union[StreamChunk, StreamError]
89
 
90
  async for chunk in self.async_iterator:
91
  if isinstance(chunk, str):
@@ -124,13 +124,13 @@ class AsyncResponseDataStreamer:
124
  final_response = error_response
125
 
126
  # Only the stream that acquires the lock should write the error response
127
- if self.lock.locked():
128
  self.ensure_response_is_created(client_response)
129
  client_response.set_status(500, reason="Internal error")
130
  client_response.write(error_response.encode('utf-8'))
131
  finally:
132
  # Only the stream that acquires the lock should close the response
133
- if self.lock.locked():
134
  self.ensure_response_is_created(client_response)
135
  # Ensure to close the response properly
136
  await client_response.write_eof()
 
34
  data = json.dumps(self.dict(), indent=4)
35
  return data.encode(encoding)
36
 
37
+ ProcessedStreamResponse = Union[StreamChunk, StreamError]
38
 
39
  class AsyncResponseDataStreamer:
40
  def __init__(self, async_iterator: AsyncIterator, selected_uid:int, lock: asyncio.Lock, delay: float = 0.1):
 
77
  return initiated_response
78
 
79
 
80
+ async def stream(self, request: web.Request) -> ProcessedStreamResponse:
 
81
  # response = web_response.StreamResponse(status=200, reason="OK")
82
  # response.headers["Content-Type"] = "application/json"
83
  # await response.prepare(request) # Prepare and send the headers
 
85
  try:
86
  start_time = time.time()
87
  client_response: web.Response = None
88
+ final_response: ProcessedStreamResponse
89
 
90
  async for chunk in self.async_iterator:
91
  if isinstance(chunk, str):
 
124
  final_response = error_response
125
 
126
  # Only the stream that acquires the lock should write the error response
127
+ if self.lock_acquired:
128
  self.ensure_response_is_created(client_response)
129
  client_response.set_status(500, reason="Internal error")
130
  client_response.write(error_response.encode('utf-8'))
131
  finally:
132
  # Only the stream that acquires the lock should close the response
133
+ if self.lock_acquired:
134
  self.ensure_response_is_created(client_response)
135
  # Ensure to close the response properly
136
  await client_response.write_eof()