一键导入
event-driven
Use when implementing async processing, background jobs, webhooks, real-time events, or message queues in Go or Python applications
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when implementing async processing, background jobs, webhooks, real-time events, or message queues in Go or Python applications
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when the user wants to free disk space, investigate disk usage, clean caches, remove unused artifacts, or when disk capacity is high. Also use when asked to "clean up", "free space", "disk full", or "what's using disk space". Always uses AskUserQuestion for every deletion decision.
Use at the start of every conversation and for every user message — orchestrates the full engineering skills suite by understanding intent, clarifying requirements interactively, and invoking the right skills
Use when refactoring Go code, cleaning up legacy codebases, optimizing performance, or enforcing clean architecture boundaries in a Go/Fiber backend
Use when refactoring Python code, cleaning up legacy codebases, optimizing performance, enforcing type safety, or improving clean architecture in a FastAPI backend
Use when refactoring React components, cleaning up legacy frontends, optimizing performance, improving component architecture, or reducing bundle size
Use when reviewing changed code before committing or after completing a feature — checks performance, architecture, type safety, and code quality against project standards
| name | event-driven |
| description | Use when implementing async processing, background jobs, webhooks, real-time events, or message queues in Go or Python applications |
Patterns for async processing, background jobs, event publishing, and webhook handling. When synchronous request-response isn't enough.
Core principle: Use events for work that doesn't need to block the user's request. Keep the request path fast.
digraph decide {
"Does user need immediate result?" -> "Synchronous (REST)" [label="yes"]
"Does user need immediate result?" -> "Must guarantee delivery?" [label="no"]
"Must guarantee delivery?" -> "Persistent queue (Redis/NATS/Kafka)" [label="yes"]
"Must guarantee delivery?" -> "Fire-and-forget (goroutine/task)" [label="no"]
}
Go — goroutine with errgroup:
// Fire-and-forget (non-critical)
go func() {
if err := emailService.SendWelcome(ctx, user); err != nil {
slog.Error("failed to send welcome email", "error", err, "user_id", user.ID)
}
}()
// With graceful shutdown tracking
g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
return emailService.SendWelcome(ctx, user)
})
// Don't wait in handler — track in service lifecycle
Python — background tasks (FastAPI):
from fastapi import BackgroundTasks
@router.post("/users", status_code=201)
async def create_user(
body: CreateUserRequest,
background_tasks: BackgroundTasks,
use_case: CreateUserUseCase = Depends(get_create_user),
) -> UserResponse:
user = await use_case.execute(body.to_input())
background_tasks.add_task(send_welcome_email, user.email, user.name)
return UserResponse.from_domain(user)
Go — publish:
type EventPublisher struct {
rdb *redis.Client
}
func (p *EventPublisher) Publish(ctx context.Context, topic string, event any) error {
data, err := json.Marshal(event)
if err != nil {
return fmt.Errorf("marshal event: %w", err)
}
return p.rdb.Publish(ctx, topic, data).Err()
}
// Usage
publisher.Publish(ctx, "user.created", UserCreatedEvent{
UserID: user.ID,
Email: user.Email,
})
Go — subscribe:
func (s *EventSubscriber) Subscribe(ctx context.Context, topic string, handler func([]byte) error) {
sub := s.rdb.Subscribe(ctx, topic)
ch := sub.Channel()
for msg := range ch {
if err := handler([]byte(msg.Payload)); err != nil {
slog.Error("event handler failed", "topic", topic, "error", err)
}
}
}
Python — publish/subscribe:
import redis.asyncio as redis
class EventPublisher:
def __init__(self, redis_client: redis.Redis) -> None:
self._redis = redis_client
async def publish(self, topic: str, event: dict) -> None:
await self._redis.publish(topic, json.dumps(event))
class EventSubscriber:
def __init__(self, redis_client: redis.Redis) -> None:
self._pubsub = redis_client.pubsub()
async def subscribe(self, topic: str, handler: Callable) -> None:
await self._pubsub.subscribe(topic)
async for message in self._pubsub.listen():
if message["type"] == "message":
await handler(json.loads(message["data"]))
// Receive webhook with signature verification
func (h *WebhookHandler) HandleStripeWebhook(c fiber.Ctx) error {
body := c.Body()
sig := c.Get("Stripe-Signature")
event, err := webhook.ConstructEvent(body, sig, webhookSecret)
if err != nil {
return pkg.NewError("unauthorized", "Invalid webhook signature", 401)
}
switch event.Type {
case "payment_intent.succeeded":
return h.handlePaymentSuccess(c.Context(), event)
case "customer.subscription.deleted":
return h.handleSubscriptionCanceled(c.Context(), event)
default:
slog.Info("unhandled webhook event", "type", event.Type)
}
return c.SendStatus(200)
}
Webhook best practices:
type WebhookSender struct {
client *http.Client
}
func (s *WebhookSender) Send(ctx context.Context, url string, event any) error {
body, _ := json.Marshal(event)
// Sign payload
mac := hmac.New(sha256.New, []byte(webhookSecret))
mac.Write(body)
signature := hex.EncodeToString(mac.Sum(nil))
req, _ := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Webhook-Signature", signature)
resp, err := s.client.Do(req)
if err != nil {
return fmt.Errorf("webhook delivery failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
// Retry with exponential backoff
return fmt.Errorf("webhook returned %d", resp.StatusCode)
}
return nil
}
// Events are past-tense, immutable facts
type UserCreatedEvent struct {
EventID uuid.UUID `json:"event_id"`
Timestamp time.Time `json:"timestamp"`
UserID uuid.UUID `json:"user_id"`
Email string `json:"email"`
}
// Name convention: [entity].[action] in past tense
// user.created, payment.succeeded, invitation.accepted
claude-md)system-designgo-feature or py-feature for the handlers