diff --git a/src/socketify/loop.py b/src/socketify/loop.py index 2937a54..90d70fd 100644 --- a/src/socketify/loop.py +++ b/src/socketify/loop.py @@ -36,6 +36,9 @@ class Loop: self.started = False self.last_defer = False + def set_timeout(self, timeout, callback, user_data): + return self.uv_loop.create_timer(timeout, 0, callback, user_data) + def create_future(self): return self.loop.create_future() diff --git a/src/socketify/native/src/libsocketify.c b/src/socketify/native/src/libsocketify.c index 82f4e49..578612f 100644 --- a/src/socketify/native/src/libsocketify.c +++ b/src/socketify/native/src/libsocketify.c @@ -120,20 +120,4 @@ void socketify_timer_destroy(socketify_timer* timer){ uv_timer_stop(timer->uv_timer_ptr); free(timer->uv_timer_ptr); free(timer); -} - -// int socketify_set_timeout(socketify_loop* loop, int64_t timeout, socketify_timer_handler handler, void* user_data){ - -// uv_timer_t* timer = malloc(sizeof(uv_timer_t)); -// if(!uv_timer_init(loop->uv_loop, timer)){ -// free(timer); -// return -1; -// } -// uv_handle_set_data((uv_handle_t*)timer, handler); -// uv_timer_start(timer, socketify_generic_timer_callback, timeout, 0); -// return 0; -// } - -// int uv_timer_init(uv_loop_t *loop, uv_timer_t *handle) - -// int uv_timer_start(uv_timer_t *handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat) +} \ No newline at end of file diff --git a/src/socketify/socketify.py b/src/socketify/socketify.py index 562df36..72dba09 100644 --- a/src/socketify/socketify.py +++ b/src/socketify/socketify.py @@ -287,7 +287,7 @@ def uws_generic_on_writable_handler(res, offset, user_data): return res.trigger_writable_handler(offset) return False -global_lock = Lock() + @ffi.callback("void(uws_res_t *, void*)") def uws_generic_cork_handler(res, user_data): if not user_data == ffi.NULL: @@ -300,7 +300,7 @@ def uws_generic_cork_handler(res, user_data): print("Error on cork handler %s" % str(err)) # response.grab_aborted_handler() # app.trigger_error(err, response, request) - global_lock.release() + class AppRequest: def __init__(self, request): self.req = request @@ -413,9 +413,9 @@ class AppResponse: def cork(self, callback): if not self.aborted: - global_lock.acquire(True) self._cork_handler = callback - lib.uws_res_cork(self.SSL, self.res, uws_generic_cork_handler, self._ptr) + #just add to uv loop in next tick to garantee corking works properly + self.loop.set_timeout(0, lambda instance: lib.uws_res_cork(instance.SSL, instance.res, uws_generic_cork_handler, instance._ptr), self) def set_cookie(self, name, value, options={}): if self._write_jar == None: diff --git a/src/tests.py b/src/tests.py index 95af363..806e5f1 100644 --- a/src/tests.py +++ b/src/tests.py @@ -25,13 +25,15 @@ import os import multiprocessing import asyncio -def corked(res): - res.write("Test ") - res.end("Hello, World!") - + async def home(res, req): # res.write_header("Content-Type", "plain/text") await asyncio.sleep(0) + + def corked(res): + res.write("Test ") + res.end("Hello, World!") + res.cork(corked) # res.write("Test ") # res.end("Hello, World!") diff --git a/tests/examples/router_and_basics.py b/tests/examples/router_and_basics.py index 5bab2b8..0da5107 100644 --- a/tests/examples/router_and_basics.py +++ b/tests/examples/router_and_basics.py @@ -45,7 +45,7 @@ def user(res, req): async def delayed_hello(delay, res): await asyncio.sleep(delay) #do something async - res.end("Hello sorry for the delay!") + res.cork(lambda res: res.end("Hello sorry for the delay!")) def delayed(res, req): #request object only lives during the life time of this call @@ -66,7 +66,7 @@ async def sleepy_json(res, req): #req maybe will not be available in direct attached async functions after await #but if you dont care about req info you can do it await asyncio.sleep(2) #do something async - res.end({ "message": "I'm delayed!", "user-agent": user_agent}) + res.cork(lambda res: res.end({ "message": "I'm delayed!", "user-agent": user_agent})) def custom_header(res, req): res.write_header("Content-Type", "application/octet-stream") diff --git a/tests/examples/upload_or_post.py b/tests/examples/upload_or_post.py index 0d3cc68..57f8d38 100644 --- a/tests/examples/upload_or_post.py +++ b/tests/examples/upload_or_post.py @@ -10,7 +10,7 @@ def upload(res, req): def on_data(res, chunk, is_end): print(f"Got chunk of data with length {len(chunk)}, is_end: {is_end}") if (is_end): - res.end("Thanks for the data!") + res.cork(lambda res: res.end("Thanks for the data!")) res.on_data(on_data) @@ -24,7 +24,7 @@ async def upload_chunks(res, req): print(f"Got chunk of data with length {len(chunk)}") #We respond when we are done - res.end("Thanks for the data!") + res.cork(lambda res: res.end("Thanks for the data!")) async def upload_json(res, req): print(f"Posted to {req.get_url()}") @@ -35,7 +35,7 @@ async def upload_json(res, req): print(f"First person is named: {people[0]['name']}") #We respond when we are done - res.end("Thanks for the data!") + res.cork(lambda res: res.end("Thanks for the data!")) async def upload_text(res, req): print(f"Posted to {req.get_url()}") @@ -45,7 +45,7 @@ async def upload_text(res, req): print(f"Your text is ${text}") #We respond when we are done - res.end("Thanks for the data!") + res.cork(lambda res: res.end("Thanks for the data!")) async def upload_urlencoded(res, req): print(f"Posted to {req.get_url()}") @@ -55,7 +55,7 @@ async def upload_urlencoded(res, req): print(f"Your form is ${form}") #We respond when we are done - res.end("Thanks for the data!") + res.cork(lambda res: res.end("Thanks for the data!")) async def upload_multiple(res, req): @@ -72,7 +72,7 @@ async def upload_multiple(res, req): print(f"Your data is ${data}") #We respond when we are done - res.end("Thanks for the data!") + res.cork(lambda res: res.end("Thanks for the data!")) app = App()