Firework Help

Bootstrap

这不是正式文档,不过我希望这足够详细以方便后来者。

介绍

Bootstrap,即 firework.bootstrap ,是用于统一管理组件内部的生命周期,以及在此之上处理组件之间依赖关系的子系统。它通过将组件的生命周期简单的划分为 prepare, online, cleanup 三个阶段,并利用 asyncio 实现了并行高效简洁的介面。

服务

Bootstrap 的组件以服务(Service)的形式存在,服务的基类可以直接从 firework.bootstrap 导入。在派生时,需填写 id 静态字段并实现 launch 方法。

from firework.bootstrap import Service, ServiceContext class MyService(Service): id = 'my_service' async def launch(self, ctx: ServiceContext): ...

launch 方法中,你需要使用 ServiceContext 提供的三个生命周期方法。

async def launch(self, ctx: ServiceContext): async with ctx.prepare(): ... async with ctx.online(): ... async with ctx.cleanup(): ...

建议在 prepare 阶段进行初始化工作, online 阶段进行主要工作, cleanup 阶段进行清理工作。

ctx.wait_for_sigexit 方法和 ctx.should_exit 属性可以用于处理退出信号。

async def launch(self, ctx: ServiceContext): async with ctx.prepare(): ... async with ctx.online(): while not ctx.should_exit: ... # or await ctx.wait_for_sigexit() async with ctx.cleanup(): ...

在完成这一切后,你可以通过 firework.bootstrap 提供的 Bootstrap 类来启动服务。

from firework.bootstrap import Bootstrap bs = Bootstrap() bs.add_initial_services(MyService()) bs.launch_blocking()

依赖

Service 中声明 dependencies 字段,可以指定服务的依赖关系。

class MyService(Service): id = 'my_service' dependencies = ['another_service'] async def launch(self, ctx: ServiceContext): ...

在启动时,Bootstrap 会自动检查依赖关系并按照依赖关系的顺序并行启动并调度服务。如果依赖关系存在循环,Bootstrap 会抛出异常。

动态增减任务

Bootstrap 可以使用 start_lifespan 方法在运行时动态增减任务,这一特性可以用于实现热重载等功能。

bs = Bootstrap() async def some_task(): online_dispatch = await bs.start_lifespan([MyService()]) # start_lifespan 方法会等待服务完成 prepare 阶段,并返回一个回调函数 online_dispatch. # 调用 online_dispatch 回调以指示服务进入并开始 online 阶段。 # 这会返回一个 cleanup_dispatch 回调,用于结束服务。 cleanup_dispatch = online_dispatch() # 调用 cleanup_dispatch 回调以指示服务进入并开始 cleanup 阶段。 await cleanup_dispatch()

处理异常

start_lifespan 方法允许你传入一个用于盛放失败任务的 list。

bs = Bootstrap() async def some_task(): failed_services = [] online_dispatch = await bs.start_lifespan( [MyService()], failed_record=failed_services, ) # ... cleanup_dispatch = online_dispatch() # ... await cleanup_dispatch() if failed_services: # 处理失败的服务 pass

如果你希望在 prepare 阶段的某个步骤失败时回滚其影响,向 start_lifespan 方法传入 rollback=True

bs = Bootstrap() async def some_task(): failed_services = [] online_dispatch = await bs.start_lifespan( [MyService()], failed_record=failed_services, rollback=True, ) # ... cleanup_dispatch = online_dispatch() # ... await cleanup_dispatch() if failed_services: # 处理失败的服务 pass

Initial Services

Bootstrap 提供了 add_initial_servicesremove_initial_services 方法,用于指定在第一次调用 launch_blocking 时启动的服务。

bs = Bootstrap() bs.add_initial_services(service := MyService()) bs.remove_initial_services(service) bs.add_initial_services(service) bs.launch_blocking()

总结

Bootstrap 在 Firework 中主要随 firework run 启动,其他子系统只构造 Service 并将状态托管其上。

firework run 负责从 firework.toml 中读取配置,使用辅助函数构造服务实例并托管给 Bootstrap。 除此之外还负责初始化 firework.config 子系统,具体的详情请参考其他文档。

Last modified: 22 November 2024