Skip to content

Commit 996637c

Browse files
committed
Add asginl interface to skip ASGI lifespan (#153)
1 parent d8698e6 commit 996637c

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ Options:
8282
GRANIAN_HOST; default: 127.0.0.1]
8383
--port INTEGER Port to bind to. [env var: GRANIAN_PORT;
8484
default: 8000]
85-
--interface [asgi|rsgi|wsgi] Application interface type [env var:
85+
--interface [asgi|asginl|rsgi|wsgi]
86+
Application interface type [env var:
8687
GRANIAN_INTERFACE; default: rsgi]
8788
--http [auto|1|2] HTTP version [env var: GRANIAN_HTTP;
8889
default: auto]

granian/asgi.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ async def handle(self):
3333
if self.failure_startup or self.failure_shutdown:
3434
return
3535
self.unsupported = True
36-
logger.warn('ASGI Lifespan errored, continuing without Lifespan support')
36+
logger.warn(
37+
'ASGI Lifespan errored, continuing without Lifespan support '
38+
'(to avoid Lifespan completely use "asginl" interface)'
39+
)
3740
finally:
3841
self.event_startup.set()
3942
self.event_shutdown.set()

granian/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
class Interfaces(str, Enum):
55
ASGI = 'asgi'
6+
ASGINL = 'asginl'
67
RSGI = 'rsgi'
78
WSGI = 'wsgi'
89

granian/server.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,49 @@ def _spawn_asgi_worker(
164164
setproctitle.setproctitle(f'{process_name} worker-{worker_id}')
165165
configure_logging(log_level, log_config, log_enabled)
166166

167+
loop = loops.get(loop_impl)
168+
sfd = socket.fileno()
169+
callback = callback_loader()
170+
171+
shutdown_event = set_loop_signals(loop, [signal.SIGTERM, signal.SIGINT])
172+
173+
wcallback = _asgi_call_wrap(callback, scope_opts, {})
174+
if not loop_opt:
175+
wcallback = future_watcher_wrapper(wcallback)
176+
177+
worker = ASGIWorker(
178+
worker_id, sfd, threads, pthreads, http_mode, http1_settings, http2_settings, websockets, loop_opt, *ssl_ctx
179+
)
180+
serve = getattr(worker, {ThreadModes.runtime: 'serve_rth', ThreadModes.workers: 'serve_wth'}[threading_mode])
181+
serve(wcallback, loop, contextvars.copy_context(), shutdown_event)
182+
183+
@staticmethod
184+
def _spawn_asgi_lifespan_worker(
185+
worker_id,
186+
process_name,
187+
callback_loader,
188+
socket,
189+
loop_impl,
190+
threads,
191+
pthreads,
192+
threading_mode,
193+
http_mode,
194+
http1_settings,
195+
http2_settings,
196+
websockets,
197+
loop_opt,
198+
log_enabled,
199+
log_level,
200+
log_config,
201+
ssl_ctx,
202+
scope_opts,
203+
):
204+
from granian._loops import loops, set_loop_signals
205+
206+
if process_name:
207+
setproctitle.setproctitle(f'{process_name} worker-{worker_id}')
208+
configure_logging(log_level, log_config, log_enabled)
209+
167210
loop = loops.get(loop_impl)
168211
sfd = socket.fileno()
169212
callback = callback_loader()
@@ -436,7 +479,8 @@ def serve(
436479
wrap_loader: bool = True,
437480
):
438481
default_spawners = {
439-
Interfaces.ASGI: self._spawn_asgi_worker,
482+
Interfaces.ASGI: self._spawn_asgi_lifespan_worker,
483+
Interfaces.ASGINL: self._spawn_asgi_worker,
440484
Interfaces.RSGI: self._spawn_rsgi_worker,
441485
Interfaces.WSGI: self._spawn_wsgi_worker,
442486
}

0 commit comments

Comments
 (0)