Skip to content
This repository has been archived by the owner on Dec 31, 2023. It is now read-only.

Lifecycle diagram #88

Open
ahopkins opened this issue Jan 4, 2022 · 7 comments
Open

Lifecycle diagram #88

ahopkins opened this issue Jan 4, 2022 · 7 comments

Comments

@ahopkins
Copy link
Member

ahopkins commented Jan 4, 2022

We should probably also include a lifecycle diagram in the docs with the flow of handlers, middleware, and signals.

Originally posted by @ahopkins in sanic-org/sanic#2352 (comment)

@ChihweiLHBird
Copy link
Member

I am exploring how the signals work but couldn't trigger http.lifecycle.read_head signal...

from asyncio import BaseEventLoop
from typing import Callable
from sanic import Sanic, Request, HTTPResponse

from sanic.response import text
from sanic.models.server_types import ConnInfo
from sanic_routing.route import Route

app = Sanic("MyHelloWorldApp")

@app.middleware("request")
async def middleware_1(request):
    print("middleware_request1")


@app.middleware("request")
async def middleware_2(request):
    print("middleware_request2")


@app.middleware("response")
async def middleware_3(request, response):
    print("middleware_response3")


@app.middleware("response")
async def middleware_4(request, response):
    print("middleware_response4")


@app.signal("http.middleware.before", condition={"attach_to": "request"})
def handle_mw_before(request, response=None):
    print("http.middleware.before request")

@app.signal("http.middleware.after", condition={"attach_to": "request"})
def handle_mw_after(request, response):
    print("http.middleware.after request")

@app.signal("http.middleware.before", condition={"attach_to": "response"})
def handle_mw_before(request, response=None):
    print("http.middleware.before response")

@app.signal("http.middleware.after", condition={"attach_to": "response"})
def handle_mw_after(request, response):
    print("http.middleware.after response")

@app.on_request
async def extract_user(request: Request):
    print("on_request")

@app.on_response
async def prevent_xss(request: Request, response: HTTPResponse):
    print("on_response")

@app.signal("http.routing.before")
async def http_routing_before(request: Request):
    print("http.routing.before")

@app.signal("http.routing.after")
async def http_routing_after(request: Request, route: Route, handler: Callable, **kwargs):
    print("http.routing.after")

@app.signal("http.lifecycle.begin")
async def http_lifecycle_begin(conn_info: ConnInfo):
    print("http.lifecycle.begin")

@app.signal("http.lifecycle.read_head")
async def http_lifecycle_read_head(head: bytes):
    print("http.lifecycle.read_head")

@app.signal("http.lifecycle.request")
async def http_lifecycle_request(request: Request):
    print("http.lifecycle.request")

@app.signal("http.lifecycle.handle")
async def http_lifecycle_handle(request: Request):
    print("http.lifecycle.handle")

@app.signal("http.lifecycle.read_body")
async def http_lifecycle_read_body(body):
    print("http.lifecycle.read_body")

@app.signal("http.lifecycle.exception")
async def http_lifecycle_exception(request: Request, exception):
    print(type(exception))
    print("http.lifecycle.exception")

@app.signal("http.lifecycle.response")
async def http_lifecycle_response(request: Request, response: HTTPResponse):
    print("http.lifecycle.response")

@app.signal("http.lifecycle.send")
async def http_lifecycle_send(data: bytes):
    print("http.lifecycle.send")

@app.signal("http.lifecycle.complete")
async def http_lifecycle_complete(conn_info: ConnInfo):
    print("http.lifecycle.complete")

@app.signal("server.init.before")
async def server_init_before(app: Sanic, loop: BaseEventLoop):
    print("server.init.before")

@app.signal("server.init.after")
async def server_init_after(app: Sanic, loop: BaseEventLoop):
    print("server.init.after")

@app.signal("server.shutdown.before")
async def server_shutdown_before(app: Sanic, loop: BaseEventLoop):
    print("server.shutdown.before")

@app.signal("server.shutdown.after")
async def server_shutdown_after(app: Sanic, loop: BaseEventLoop):
    print("server.shutdown.after")

@app.get("/")
async def hello_world(request: Request):
    print(request.body)
    return text("Hello, world.")


app.run(auto_reload=True)

@ahopkins
Copy link
Member Author

from sanic import Request, Sanic, json
from sanic.signals import Event

app = Sanic(__name__)


@app.get("/")
async def handler(request: Request):
    return json({"foo": "bar"})


@app.signal(Event.HTTP_LIFECYCLE_READ_HEAD)
async def http_lifecycle_read_head(**kwargs):
    print("HTTP_LIFECYCLE_READ_HEAD", kwargs)


@app.signal(Event.HTTP_LIFECYCLE_READ_BODY)
async def http_lifecycle_read_body(**kwargs):
    print("HTTP_LIFECYCLE_READ_BODY", kwargs)

When I curl that I see both READ_HEAD and READ_BODY executed.

@ChihweiLHBird
Copy link
Member

ChihweiLHBird commented May 11, 2022

I can only see one of them, unless put a POST request handler on the route... Not sure what I missed.

image

@ChihweiLHBird
Copy link
Member

By the way, what type of diagram do you think is appropriate for the lifecycle diagram? How about flowchart? I think the sequence diagram (used for middleware lifecycle diagram) isn't good enough for this case (signals lifecycle diagram) because it too emphasizes interactions (changes of states), where an event happens (e.g. after reading body and before executing middleware handlers).

@ahopkins
Copy link
Member Author

Yes, a flowchart makes sense.

@ahopkins
Copy link
Member Author

I can only see one of them, unless put a POST request handler on the route... Not sure what I missed.

There is no body to read (usually) on a GET. So nothing.

@ChihweiLHBird
Copy link
Member

ChihweiLHBird commented May 14, 2022

https://cdn.discordapp.com/attachments/888512290805145612/975130978676772884/unknown.png

Hi @ahopkins, This is my initial draft of the lifecycle diagram. Some details are still needed like middleware handler retuning a response directly. Other than that, may I have some feedback? Another problem I can think about is it is too large to be placed on the doc page...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants