Skip to content

Dependencies

pydantic models

fastbpmn uses the power and magic of pydantic to simplify the handling of process instance variables

from typing import Annotated
from annotated_types import Gt

from fastbpmn import FastBPMN
from fastbpmn.camunda import ProcessEngine
from fastbpmn.models import InputOutputModel

app = FastBPMN(name="Bob")

class PersonData(InputOutputModel):
    name: str
    age: Annotated[int, Gt(0)]

class MovieData(InputOutputModel):
    movie: str
    fsk: Annotated[int, Gt(0)] | None


class MovieGrant(InputOutputModel):
    greeting: str
    granted: bool


@app.external_task(
    topic="movie-access",
)
async def movie_access(person: PersonData, movie: MovieData) -> MovieGrant:
    """
    Check if the person may look at the movie or not
    """
    granted = person.age >= (movie.fsk or 0)
    greeting = f"Hello {person.name}, you are allowed to watch {movie.movie}"

    return MovieGrant(granted=granted, greeting=greeting)

dependencies

sync / async

fasbpmn supports async and sync dependencies, the latter get executed in a thread pool to avoid blocking the event loop.

functions

from typing import Annotated
from annotated_types import Gt

from fastbpmn import FastBPMN
from fastbpmn.camunda import ProcessEngine
from fastbpmn.models import InputOutputModel
from fastbpmn.params import Depends

app = FastBPMN(name="Bob")

class PersonData(InputOutputModel):
    name: str
    age: Annotated[int, Gt(0)]

class MovieData(InputOutputModel):
    movie: str
    fsk: Annotated[int, Gt(0)] | None

# can be async as well
def fetch_movie_data(movie: str) -> MovieData:
    # query some system for the fsk value
    fsk = query_fsk_from_imdb(movie)
    return MovieData(movie=movie, fsk=fsk)

class MovieGrant(InputOutputModel):
    greeting: str
    granted: bool


@app.external_task(
    topic="movie-access",
)
async def movie_access(person: PersonData, movie: dict = Depends(fetch_movie_data)) -> MovieGrant:
    """
    Check if the person may look at the movie or not
    """
    granted = person.age >= (movie.fsk or 0)
    greeting = f"Hello {person.name}, you are allowed to watch {movie.movie}"

    return MovieGrant(granted=granted, greeting=greeting)

generators (context manager)

You can also use generator functions as dependencies, e.g. to clean up after yourself.

from typing import Annotated
from annotated_types import Gt

from fastbpmn import FastBPMN
from fastbpmn.camunda import ProcessEngine
from fastbpmn.models import InputOutputModel
from fastbpmn.params import Depends

app = FastBPMN(name="Bob")

# no @contextmanager decorator allowed
# the employee_id has to be present as process variable
async def employee_data(employee_id: str):
    async with your_db_client as db:
        employee = await db.select_employee(employee_id)
        yield employee

@app.external_task(
    topic="employee-pay",
)
async def movie_access(employee: dict = Depends(employee_data)) -> None:
    """
    Check if the person may look at the movie or not
    """
    # perform employees payment

    return
    # once we exit this method the context manager gets closed