writer / writer-framework

No-code in the front, Python in the back. An open-source framework for creating data apps.
https://dev.writer.com/framework/introduction
Apache License 2.0
1.3k stars 73 forks source link

use middleware to intercept event handlers (global event, database management, ...) #471

Closed FabienArcellier closed 2 months ago

FabienArcellier commented 2 months ago

This PR implements the concept of middleware. Middleware is a function that intercepts all events. You can use it to implement session management for a database, code an extension to streamsync which globally modifies the operation of certain events, ...

Peek 2024-06-19 23-20

# MIDDLEWARES
@wf.middleware()
def count_events(state):
    state['counter_event'] += 1
    yield

@wf.middleware()
def count_specific_events(state, context):
    event_type = context.get('event')
    if event_type == 'wf-click':
        state['counter_event_click'] += 1

    if event_type == 'wf-option-change':
        state['counter_event_select'] += 1

    yield

Usecase

middleware facilitates cross-functional operations such as database transaction management. Opening a session at the start of a query is a pattern that improves the use of a database. The session links the transaction to the request. If processing fails, the transaction is rolled back. If it succeeds, the transaction is successful.

import writer as wf

engine = sa.create_engine("postgresql://admin:admin@localhost/Adventureworks", echo=True)
Session = sessionmaker(engine)

@wf.middleware
def manage_sqlalchemy_session():
    with Session() as session:
        session.begin()
        try:
            yield
            session.commit()
        except:
            session.rollback()
            raise

middleware facilitates cross-functional operations such as exception tracking.

import writer as wf

@wf.middleware
def manage_sentry_capture(state, payload):
    with sentry_sdk.configure_scope() as scope:
        scope.set_tag("site", state['site'])
        try:
            yield
        except Exception as exception:
            sentry_sdk.capture(exception)
            raise
        finally:
            scope.clear()