Éṽéñţ Šýšţéḿ àñđ Àüţöḿàţîöñ
Ţĥé éṽéñţ šýšţéḿ þŕöṽîđéš þüƃ/šüƃ ƒöŕ ŕéàçţîñĝ ţö çöñţéñţ çĥàñĝéš, ţŕîĝĝéŕîñĝ
àüţöḿàţîöñ ŕüļéš, àñđ đéļîṽéŕîñĝ ŵéƃĥööķš. Îñ à đéþļöýḿéñţ ţĥé ƃüš ŕüñš öñ
Ŕéđîš Šţŕéàḿš (BOWRAIN_EVENT_BACKEND=redis), šĥàŕéđ ƃý ţĥé šéŕṽéŕ àñđ ţĥé
ŵöŕķéŕ; ţĥé îñ-þŕöçéšš ChannelEventBus ƃéļöŵ ƃàçķš šîñĝļé-þŕöçéšš
đéṽéļöþḿéñţ àñđ ţéšţš.
ÉṽéñţƂüš
Ţĥé ChannelEventBus îš à çĥàññéļ-ƃàšéđ þüƃ/šüƃ îḿþļéḿéñţàţîöñ ŵîţĥ þéŕ-šüƃšçŕîƃéŕ ĝöŕöüţîñéš:
bus := event.NewChannelEventBus()
// Subscribe to specific event types
sub := bus.Subscribe(platev.EventBlockUpdated, func(e platev.Event) {
fmt.Printf("Block %s updated in project %s\n", e.Data["block_id"], e.ProjectID)
})
// Subscribe to all events
allSub := bus.SubscribeAll(func(e platev.Event) {
fmt.Printf("Event: %s\n", e.Type)
})
// Unsubscribe
bus.Unsubscribe(sub)
Ţĥé éṽéñţ ţýþéš àŕé đéçļàŕéđ îñ bowrain/core/event (îḿþöŕţéđ àš platev
àƃöṽé); ţĥé ƃüš, ţĥé éḿîţţîñĝ šţöŕé đéçöŕàţöŕ, ţĥé àüţöḿàţîöñ éñĝîñé àñđ
ŵéƃĥööķ đéļîṽéŕý ļîṽé îñ bowrain/event.
Éṽéñţ Ţýþéš
| Éṽéñţ | Éḿîţţéđ ŵĥéñ |
|---|---|
block.created | À ƃļöçķ îš šţöŕéđ ƒöŕ ţĥé ƒîŕšţ ţîḿé |
block.updated | À ƃļöçķ îš üþđàţéđ |
block.deleted | À ƃļöçķ îš đéļéţéđ |
project.created | À þŕöĵéçţ îš çŕéàţéđ |
project.updated | À þŕöĵéçţ îš üþđàţéđ |
project.deleted | À þŕöĵéçţ îš đéļéţéđ |
version.created | À ṽéŕšîöñ šñàþšĥöţ îš çŕéàţéđ |
collection.created / collection.updated / collection.deleted | À çöļļéçţîöñ çĥàñĝéš |
item.created / item.deleted | Àñ îţéḿ îš àđđéđ öŕ ŕéḿöṽéđ |
connector.pull.completed | À þüļļ ƒŕöḿ à çöññéçţöŕ çöḿþļéţéš |
connector.push.completed | À þüšĥ çöḿþļéţéš |
connector.sync.completed | À çöññéçţöŕ šýñç çöḿþļéţéš |
push.automations.completed | Éṽéŕý àüţöḿàţîöñ ƒöŕ à þüšĥ ĥàš çöḿþļéţéđ |
convergence.run.completed | À ŕüñ ƒîñîšĥéš |
flow.started | À ƒļöŵ ƃéĝîñš éẋéçüţîöñ |
flow.completed / flow.failed | Đéçļàŕéđ; ñö éẋéçüţîöñ þàţĥ éḿîţš ţĥéḿ, šö ñö àüţöḿàţîöñ ţŕîĝĝéŕ ƒîŕéš öñ à ƒļöŵ ƒîñîšĥîñĝ |
extraction.completed | Ţéŕḿ éẋţŕàçţîöñ çöḿþļéţéš |
quality.gate.pass / quality.gate.fail | À ļàñĝüàĝé'š šĥîþ-ĝàţé ŕéšüļţ çĥàñĝéš |
source.review.completed | À šöüŕçé ŕéṽîéŵ ţàšķ îš çöḿþļéţéđ |
review.completed | À þŕöĵéçţ'š ŕéṽîéŵ ǫüéüé îš éḿþţîéđ |
review.decided | Öñé ƃļöçķ'š ţàŕĝéţ îš àþþŕöṽéđ, ŕéĵéçţéđ, öŕ üñ-ŕéṽîéŵéđ |
review.bulk_approved | Àñ àþþŕöṽé-þàššîñĝ þàšš þŕöḿöţéš à ļàñĝüàĝé'š þàššîñĝ ţàŕĝéţš |
voice.check.started / voice.check.completed | À ṽöîçé çĥéçķ ŕüñš |
voice.drift / voice.corrected / voice.profile.updated | Ţĥé ṽöîçé ļööþ ḿöṽéš |
stream.created / stream.merged / stream.deleted / stream.locked / stream.unlocked / stream.tagged | À šţŕéàḿ çĥàñĝéš |
member.*, role.template.*, invite.*, token.*, auth.*, session.grant.created, authz.denied | Ḿéḿƃéŕšĥîþ àñđ àççéšš |
rollback.performed, platform_config.changed | Àđḿîñîšţŕàţîöñ |
agent.* | Ţĥé îñ-þŕöđüçţ àĝéñţ (đàŕķ ƃý đéƒàüļţ) |
Ţĥé çàñöñîçàļ ļîšţ îš ţĥé EventType çöñšţàñţš îñ
bowrain/core/event/event.go. Ţĥé àüţöḿàţîöñ éđîţöŕ öƒƒéŕš öñļý ţĥé ţýþéš àñ
éẋéçüţîöñ þàţĥ éḿîţš.
ÉṽéñţÉḿîţţîñĝŠţöŕé
Ţĥé EventEmittingStore đéçöŕàţöŕ ŵŕàþš à ContentStore àñđ éḿîţš éṽéñţš öñ àļļ ḿüţàţîöñš:
cs, err := sqlitestore.NewSQLiteStore("working-copy.db")
if err != nil {
log.Fatal(err)
}
bus := event.NewChannelEventBus()
emittingStore := event.NewEventEmittingStore(cs, bus)
Àüţöḿàţîöñ Ŕüļéš
Ţĥé àüţöḿàţîöñ éñĝîñé éṽàļüàţéš ŕüļéš ţŕîĝĝéŕéđ ƃý éṽéñţš. Îţ ţàķéš ţĥé ƃüš àñđ
àñ ActionExecutor, ŵĥîçĥ ŕüñš à ŕüļé'š àçţîöñš (run_flow, notify, àñđ
ţĥé ŕéšţ) ŵĥéñ à ŕüļé ḿàţçĥéš:
engine := event.NewAutomationEngine(bus, executor)
engine.AddRule(event.AutomationRule{
Name: "auto-draft-on-push",
EventType: platev.EventPushCompleted,
Conditions: []event.Condition{
{Field: "project_id", Operator: "equals", Value: "proj-1"},
},
// Actions are executed by the ActionExecutor.
})
engine.Start(ctx)
Ļööþ Þŕéṽéñţîöñ
Àüţöḿàţîöñ çĥàîñš àŕé ţŕàçķéđ ṽîà CausationID. ΃ à çĥàîñ éẋçééđš ţĥé ḿàẋîḿüḿ đéþţĥ (đéƒàüļţ 5), îţ îš àüţöḿàţîçàļļý ƃŕöķéñ ţö þŕéṽéñţ îñƒîñîţé ļööþš.
Ǫüàļîţý ĝàţé éṽéñţš
Ţĥé šéŕṽéŕ þüƃļîšĥéš quality.gate.fail àñđ quality.gate.pass ƒŕöḿ ţĥé šĥîþ
ĝàţé (bowrain/server/shipgate_events.go). Éàçĥ ţîḿé îţ đéŕîṽéš à þŕöĵéçţ'š
šĥîþ šţàţéš, öñ à đàšĥƃöàŕđ öŕ šĥîþ-ƒééđ ŕéàđ àñđ ŵĥéñ à çöñṽéŕĝéñçé ŕüñ éñđš,
îţ çöḿþàŕéš éàçĥ ļàñĝüàĝé'š ĝàţéš (store.ShipGateResults) ŵîţĥ ţĥé ƒàîļüŕéš
îţ ĥàš àļŕéàđý àññöüñçéđ, ŵĥîçĥ ţĥé çöñţéñţ šţöŕé ķééþš îñ ship_gate_failures:
- Àñ üñḿéţ ĝàţé ŵîţĥ ñö àññöüñçéđ ƒàîļüŕé, öŕ ŵĥöšé
not_checkedṽàļüé çĥàñĝéđ, þüƃļîšĥéšquality.gate.failàñđ îš ŕéçöŕđéđ. - Àñ àññöüñçéđ ƒàîļüŕé ŵĥöšé ĝàţé îš ḿéţ àĝàîñ þüƃļîšĥéš
quality.gate.passàñđ îš çļéàŕéđ. - Àñý öţĥéŕ ŕéšüļţ þüƃļîšĥéš ñöţĥîñĝ. À ĝàţé ţĥé đéŕîṽàţîöñ đîđ ñöţ éṽàļüàţé, šüçĥ àš ţĥé çĥéçķš ƃéļöŵ ƒüļļ çöṽéŕàĝé, öþéñš àñđ çļéàŕš ñöţĥîñĝ.
Ţĥé ĝàţéš àŕé translated, checks, terms, stale àñđ rejected. Éàçĥ
éṽéñţ çàŕŕîéš ţĥé þŕöĵéçţ îñ ProjectID àñđ ţĥîš đàţà:
| Ķéý | Ṽàļüé |
|---|---|
gate_name | Ţĥé ĝàţé |
locale | Ţĥé ļàñĝüàĝé |
stream | Ţĥé šţŕéàḿ ţĥé çöñţéñţ îš öñ |
actual | Ţŕàñšļàţéđ ƃļöçķš ƒöŕ translated, àñđ ƃļöçķš àţ ƒàüļţ ƒöŕ éṽéŕý öţĥéŕ ĝàţé |
required | Ţöţàļ ƃļöçķš ƒöŕ translated, àñđ 0 ƒöŕ éṽéŕý öţĥéŕ ĝàţé |
not_checked | true ŵĥéñ ţĥé ĝàţé îš üñḿéţ ƃéçàüšé ţĥé ļàñĝüàĝé ĥàš ñö çöñţéñţ öŕ à çĥéçķ ĥàš ñö ŕéšüļţ |
ship_state | Ţĥé ļàñĝüàĝé'š đéŕîṽéđ šĥîþ šţàţé |
workspace_id, workspace_slug | Ţĥé þŕöĵéçţ'š ŵöŕķšþàçé |
À ƒàîļüŕé ñöţîƒîçàţîöñ çàŕŕîéš ţĥé ĝŕöüþ ķéý
quality-gate:<project>:<stream>:<gate>:<locale> (event.QualityGateGroupKey),
àñđ ţĥé þàšš ƒöŕ ţĥé šàḿé ĝàţé ḿàŕķš îţ ŕéàđ. Ţĥé éṽéñţš ƃļöçķ ñö öþéŕàţîöñ.
Ŵéƃĥööķš
Ŵéƃĥööķ đéļîṽéŕý ŵîţĥ ĤḾÀÇ-ŠĤÀ256 šîĝñîñĝ àñđ ŕéţŕý îš à ļîƃŕàŕý þŕîḿîţîṽé îñ
bowrain/event; ñö ŵöŕķšþàçé-ƒàçîñĝ šüŕƒàçé çöñƒîĝüŕéš öüţƃöüñđ ŵéƃĥööķš.
wh := event.WebhookDelivery{
URL: "https://example.com/webhook",
Secret: "shared-secret",
}
err := wh.Deliver(ctx, eventData)
Šîĝñàţüŕé ṽéŕîƒîçàţîöñ öñ ţĥé ŕéçéîṽîñĝ éñđ:
valid := event.VerifySignature(payload, signature, secret)