CheeseAPI 2.0.6b3__tar.gz → 2.0.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/app.py +2 -1
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/scheduler.py +32 -55
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/validator.py +7 -5
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/websocket.py +38 -30
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/PKG-INFO +1 -1
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/pyproject.toml +1 -1
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/.gitignore +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/__init__.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/cors.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/file.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/printer.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/request.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/response.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/route.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/signal.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/CheeseAPI/static.py +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/LICENSE +0 -0
- {cheeseapi-2.0.6b3 → cheeseapi-2.0.7}/README.md +0 -0
|
@@ -334,7 +334,8 @@ class AppProxy:
|
|
|
334
334
|
async def get_response(self, request: Request) -> Response:
|
|
335
335
|
if inspect.isfunction(request.fn):
|
|
336
336
|
try:
|
|
337
|
-
|
|
337
|
+
signature = inspect.signature(request.fn)
|
|
338
|
+
if 'request' in signature.parameters or any(p.kind == inspect.Parameter.VAR_KEYWORD for p in signature.parameters.values()):
|
|
338
339
|
return await request.fn(request = request)
|
|
339
340
|
else:
|
|
340
341
|
return await request.fn()
|
|
@@ -258,11 +258,11 @@ class SchedulerProxy:
|
|
|
258
258
|
coro.close()
|
|
259
259
|
|
|
260
260
|
def _start_pubsub(self, app: 'CheeseAPI'):
|
|
261
|
-
pubsub = redis.Redis(connection_pool = static.scheduler_sync_servers[0]).pubsub()
|
|
262
|
-
pubsub.subscribe('CheeseAPI_scheduler')
|
|
263
261
|
try:
|
|
264
262
|
while True:
|
|
265
263
|
try:
|
|
264
|
+
pubsub = redis.Redis(connection_pool = static.scheduler_sync_servers[0]).pubsub()
|
|
265
|
+
pubsub.subscribe('CheeseAPI_scheduler')
|
|
266
266
|
for message in pubsub.listen():
|
|
267
267
|
if message['type'] == 'message':
|
|
268
268
|
data = json.loads(message['data'])
|
|
@@ -278,9 +278,7 @@ class SchedulerProxy:
|
|
|
278
278
|
elif data[0] == 'remove':
|
|
279
279
|
self.remove(data[1])
|
|
280
280
|
except redis.exceptions.RedisError:
|
|
281
|
-
pubsub.close()
|
|
282
281
|
time.sleep(app.sync_server_timeout)
|
|
283
|
-
self._start_pubsub(app)
|
|
284
282
|
except (KeyboardInterrupt, SystemExit):
|
|
285
283
|
...
|
|
286
284
|
|
|
@@ -353,49 +351,36 @@ class SchedulerProxy:
|
|
|
353
351
|
|
|
354
352
|
def task_processing(self, key: str, queue: multiprocessing.Queue, fn, *args, **kwargs):
|
|
355
353
|
try:
|
|
356
|
-
task = self.get_task(key)
|
|
357
|
-
if not task:
|
|
358
|
-
return
|
|
359
|
-
|
|
360
354
|
queue.get()
|
|
361
|
-
first_run = True
|
|
362
355
|
|
|
356
|
+
task = self.get_task(key)
|
|
357
|
+
if static.scheduler_sync_servers:
|
|
358
|
+
task._queue.get()
|
|
363
359
|
if task.first_run_timer:
|
|
364
360
|
time.sleep(max(0, task.first_run_timer.timestamp() - time.time()))
|
|
365
361
|
|
|
366
362
|
while not queue.qsize():
|
|
367
|
-
if static.scheduler_sync_servers:
|
|
368
|
-
task = self.get_task(key)
|
|
369
|
-
if (not task or (not first_run and task._queue.qsize())):
|
|
370
|
-
break
|
|
371
|
-
|
|
372
363
|
now = time.time()
|
|
373
364
|
|
|
374
365
|
try:
|
|
375
|
-
|
|
366
|
+
signature = inspect.signature(fn)
|
|
367
|
+
has_kwargs = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in signature.parameters.values())
|
|
368
|
+
if 'app' in signature.parameters or has_kwargs:
|
|
376
369
|
fn(*args, app = self.app, **kwargs)
|
|
377
370
|
else:
|
|
378
371
|
fn(*args, **kwargs)
|
|
379
372
|
except Exception as e:
|
|
380
373
|
self.app.printer.scheduler_error(e, task)
|
|
381
374
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if task:
|
|
386
|
-
task._last_run_time = time.time() - now
|
|
387
|
-
task._last_run_timer = datetime.datetime.fromtimestamp(now)
|
|
388
|
-
task._run_num += 1
|
|
389
|
-
|
|
390
|
-
if static.scheduler_sync_servers:
|
|
391
|
-
sync_server = redis.Redis(connection_pool = static.scheduler_sync_servers[0])
|
|
392
|
-
sync_server.hset('CheeseAPI_scheduler_tasks', key, json.dumps(task._to_dict()))
|
|
393
|
-
sync_server.hpexpire('CheeseAPI_scheduler_tasks', int(task.timeout * 1000), key)
|
|
375
|
+
task._last_run_time = time.time() - now
|
|
376
|
+
task._last_run_timer = datetime.datetime.fromtimestamp(now)
|
|
377
|
+
task._run_num += 1
|
|
394
378
|
|
|
395
|
-
if
|
|
396
|
-
|
|
379
|
+
if static.scheduler_sync_servers:
|
|
380
|
+
sync_server = redis.Redis(connection_pool = static.scheduler_sync_servers[0])
|
|
381
|
+
sync_server.hset('CheeseAPI_scheduler_tasks', key, json.dumps(task._to_dict()))
|
|
382
|
+
sync_server.hpexpire('CheeseAPI_scheduler_tasks', int(task.timeout * 1000), key)
|
|
397
383
|
|
|
398
|
-
first_run = False
|
|
399
384
|
time.sleep(max(0, task.interval_time - time.time() + now))
|
|
400
385
|
except (KeyboardInterrupt, SystemExit):
|
|
401
386
|
...
|
|
@@ -404,52 +389,42 @@ class SchedulerProxy:
|
|
|
404
389
|
redis.Redis(connection_pool = static.scheduler_sync_servers[0]).hpersist('CheeseAPI_scheduler_tasks', key)
|
|
405
390
|
|
|
406
391
|
async def async_task_processing(self, key: str, queue: multiprocessing.Queue, fn, *args, **kwargs):
|
|
407
|
-
task = self.get_task(key)
|
|
408
|
-
if not task:
|
|
409
|
-
return
|
|
410
|
-
|
|
411
392
|
queue.get()
|
|
412
|
-
first_run = True
|
|
413
393
|
|
|
394
|
+
task = await self.async_get_task(key)
|
|
395
|
+
if static.scheduler_sync_servers:
|
|
396
|
+
task._queue.get()
|
|
414
397
|
if task.first_run_timer:
|
|
415
398
|
await asyncio.sleep(max(0, task.first_run_timer.timestamp() - time.time()))
|
|
416
399
|
|
|
417
400
|
while not queue.qsize():
|
|
418
|
-
if static.scheduler_sync_servers:
|
|
419
|
-
task = await self.async_get_task(key)
|
|
420
|
-
if (not task or (not first_run and task._queue.qsize())):
|
|
421
|
-
break
|
|
422
|
-
|
|
423
401
|
now = time.time()
|
|
424
402
|
|
|
425
403
|
try:
|
|
426
|
-
|
|
404
|
+
signature = inspect.signature(fn)
|
|
405
|
+
has_kwargs = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in signature.parameters.values())
|
|
406
|
+
if 'app' in signature.parameters or has_kwargs:
|
|
427
407
|
await fn(*args, app = self.app, **kwargs)
|
|
428
408
|
else:
|
|
429
409
|
await fn(*args, **kwargs)
|
|
430
410
|
except Exception as e:
|
|
431
411
|
self.app.printer.scheduler_error(e, task)
|
|
432
412
|
|
|
433
|
-
|
|
434
|
-
|
|
413
|
+
task._last_run_time = time.time() - now
|
|
414
|
+
task._last_run_timer = datetime.datetime.fromtimestamp(now)
|
|
415
|
+
task._run_num += 1
|
|
435
416
|
|
|
436
|
-
if
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
task.
|
|
440
|
-
|
|
441
|
-
if static.scheduler_sync_servers:
|
|
442
|
-
sync_server = redis.asyncio.Redis(connection_pool = static.scheduler_sync_servers[1])
|
|
443
|
-
await sync_server.hset('CheeseAPI_scheduler_tasks', key, json.dumps(task._to_dict()))
|
|
444
|
-
await sync_server.hpexpire('CheeseAPI_scheduler_tasks', int(task.timeout * 1000), key)
|
|
417
|
+
if static.scheduler_sync_servers:
|
|
418
|
+
sync_server = redis.asyncio.Redis(connection_pool = static.scheduler_sync_servers[1])
|
|
419
|
+
await sync_server.hset('CheeseAPI_scheduler_tasks', key, json.dumps(task._to_dict()))
|
|
420
|
+
await sync_server.hpexpire('CheeseAPI_scheduler_tasks', int(task.timeout * 1000), key)
|
|
445
421
|
|
|
446
|
-
if
|
|
422
|
+
if task.run_num_completed:
|
|
447
423
|
break
|
|
448
424
|
|
|
449
|
-
first_run = False
|
|
450
425
|
await asyncio.sleep(max(0, task.interval_time - time.time() + now))
|
|
451
426
|
|
|
452
|
-
if
|
|
427
|
+
if task.auto_remove:
|
|
453
428
|
self._tasks.pop(key, None)
|
|
454
429
|
if static.scheduler_sync_servers is not None:
|
|
455
430
|
await redis.asyncio.Redis(connection_pool = static.scheduler_sync_servers[1]).hdel('CheeseAPI_scheduler_tasks', key)
|
|
@@ -526,6 +501,7 @@ class SchedulerProxy:
|
|
|
526
501
|
if static.scheduler_sync_servers:
|
|
527
502
|
redis.Redis(connection_pool = static.scheduler_sync_servers[0]).publish('CheeseAPI_scheduler', json.dumps(['remove', key]))
|
|
528
503
|
else:
|
|
504
|
+
_task._queue.put(None)
|
|
529
505
|
self._tasks.pop(key, None)
|
|
530
506
|
if static.scheduler_sync_servers:
|
|
531
507
|
redis.Redis(connection_pool = static.scheduler_sync_servers[0]).hdel('CheeseAPI_scheduler_tasks', key)
|
|
@@ -556,6 +532,7 @@ class SchedulerProxy:
|
|
|
556
532
|
if static.scheduler_sync_servers:
|
|
557
533
|
await redis.asyncio.Redis(connection_pool = static.scheduler_sync_servers[1]).publish('CheeseAPI_scheduler', json.dumps(['remove', key]))
|
|
558
534
|
else:
|
|
535
|
+
_task._queue.put(None)
|
|
559
536
|
self._tasks.pop(key, None)
|
|
560
537
|
if static.scheduler_sync_servers:
|
|
561
538
|
await redis.asyncio.Redis(connection_pool = static.scheduler_sync_servers[1]).hdel('CheeseAPI_scheduler_tasks', key)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import json
|
|
1
|
+
import json, inspect
|
|
2
2
|
from typing import Callable, TYPE_CHECKING
|
|
3
3
|
from functools import wraps
|
|
4
4
|
|
|
@@ -20,10 +20,8 @@ def validator(*, json_model: pydantic.BaseModel | None = None, form_model: pydan
|
|
|
20
20
|
|
|
21
21
|
def wrapper(fn: Callable) -> Callable:
|
|
22
22
|
@wraps(fn)
|
|
23
|
-
async def decorator(*args, **kwargs):
|
|
23
|
+
async def decorator(*args, request: 'Request', **kwargs):
|
|
24
24
|
try:
|
|
25
|
-
request: 'Request' = kwargs.get('request', None)
|
|
26
|
-
|
|
27
25
|
json_data = None
|
|
28
26
|
if json_model is not None:
|
|
29
27
|
json_data = json_model.model_validate(request.json or {}, by_alias = True)
|
|
@@ -59,6 +57,10 @@ def validator(*, json_model: pydantic.BaseModel | None = None, form_model: pydan
|
|
|
59
57
|
else:
|
|
60
58
|
return Response(json.loads(e.json()), 400)
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
signature = inspect.signature(fn)
|
|
61
|
+
if 'request' in signature.parameters or any(p.kind == inspect.Parameter.VAR_KEYWORD for p in signature.parameters.values()):
|
|
62
|
+
return await fn(*args, request = request, **kwargs)
|
|
63
|
+
else:
|
|
64
|
+
return await fn(*args, **kwargs)
|
|
63
65
|
return decorator
|
|
64
66
|
return wrapper
|
|
@@ -2,7 +2,7 @@ import base64, hashlib, asyncio, ssl, struct, json
|
|
|
2
2
|
from functools import partial
|
|
3
3
|
from typing import TYPE_CHECKING, AsyncIterable, Self
|
|
4
4
|
|
|
5
|
-
import redis
|
|
5
|
+
import redis, redis.exceptions
|
|
6
6
|
|
|
7
7
|
from CheeseAPI import static
|
|
8
8
|
from CheeseAPI.response import Response
|
|
@@ -246,35 +246,43 @@ class WebsocketProxy:
|
|
|
246
246
|
await self.websocket.on_connect()
|
|
247
247
|
|
|
248
248
|
async def sync_server_running(self):
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
249
|
+
try:
|
|
250
|
+
if self.app.sync_server_url.startswith('redis'):
|
|
251
|
+
while True:
|
|
252
|
+
try:
|
|
253
|
+
pubsub = static.websocket_sync_server[self.websocket.request.path].pubsub()
|
|
254
|
+
await pubsub.subscribe(self.websocket.request.path)
|
|
255
|
+
async for message in pubsub.listen():
|
|
256
|
+
print(message)
|
|
257
|
+
if message['type'] != 'message':
|
|
258
|
+
continue
|
|
259
|
+
|
|
260
|
+
connectors = Websocket.connectors.get(self.websocket.request.path)
|
|
261
|
+
if not connectors:
|
|
262
|
+
continue
|
|
263
|
+
|
|
264
|
+
message = message['data']
|
|
265
|
+
if static.websocket_data_decode is not None:
|
|
266
|
+
message = static.websocket_data_decode(message)
|
|
267
|
+
message = json.loads(message.decode())
|
|
268
|
+
if isinstance(message['key'], list):
|
|
269
|
+
connectors = [connector for connector in connectors if connector.key in message['key']]
|
|
270
|
+
elif isinstance(message['key'], str):
|
|
271
|
+
connectors = [connector for connector in connectors if connector.key == message['key']]
|
|
272
|
+
else:
|
|
273
|
+
connectors = [connector for connector in connectors]
|
|
274
|
+
|
|
275
|
+
if connectors:
|
|
276
|
+
if message['event'] == 'send':
|
|
277
|
+
for connector in connectors:
|
|
278
|
+
asyncio.create_task(connector.send(message['data']))
|
|
279
|
+
elif message['event'] == 'close':
|
|
280
|
+
for connector in connectors:
|
|
281
|
+
asyncio.create_task(connector.close())
|
|
282
|
+
except redis.exceptions.RedisError:
|
|
283
|
+
await asyncio.sleep(self.app.sync_server_timeout)
|
|
284
|
+
except (KeyboardInterrupt, SystemExit, asyncio.CancelledError):
|
|
285
|
+
...
|
|
278
286
|
|
|
279
287
|
async def message(self):
|
|
280
288
|
while True:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|