Przejdź do głównej treści
Automatyzacje to części aplikacji, które działają samodzielnie — zgodnie z harmonogramem lub gdy usługa zewnętna wyśle zdarzenie. Deklarujesz je w komponencie process w kazzle.config.ts. Jeden komponent może mieć tyle wyzwalaczy, ile potrzebujesz.

Struktura

{
  name: 'events',
  type: 'process',
  path: './components/events/index.ts',
  processMode: 'persistent', // lub 'triggered'
  triggers: [
    { name: 'daily-digest', kind: 'schedule', schedule: '0 9 * * *', path: '/cron/daily-digest' },
    { name: 'stripe',       kind: 'webhook',                          path: '/webhook/stripe' },
  ],
}
Tutaj zachodzą dwie rzeczy:
  • processMode określa cykl życia — długotrwały serwer lub jednorazowe uruchomienie na wyzwalacz.
  • triggers[] wymienia zdarzenia, które powinny uruchomić ten komponent.
Te dwie części są niezależne. Serwer persistent może mieć cron. Proces efemeryczny może mieć webhook. Wybierz cykl życia pasujący do obciążenia, a następnie dołącz tyle wyzwalaczy, ile chcesz.

processMode

TrybCo się uruchamiaKiedy używać
persistent (domyślnie)Długotrwały serwer HTTP. Wyzwalacze są do niego POSTowane.Komponent już obsługuje HTTP lub przechowuje stan w pamięci (kolejki, websockety, cache’e).
triggeredSkrypt wejściowy jest uruchamiany na wyzwalacz i kończy się.Czyste zadania w tle — nocne czyszczenie, obsługa pojedynczego webhooka Stripe itp. Bez bezczynnych serwerów.

Wyzwalacze

Każdy wyzwalacz ma name (unikalną w obrębie komponentu), kind i — w zależności od trybu — schedule i/lub path.
PoleKiedy wymaganeUwagi
namezawszeUżywane jako segment URL webhooka i w logach. Kebab-case.
kindzawsze'schedule' lub 'webhook'.
schedulegdy kind: 'schedule'Wyrażenie cron z 5 polami. Rozdzielczość minutowa to minimum.
pathgdy processMode: 'persistent'Trasa HTTP na serwerze, gdzie ląduje wyzwalacz.

Tryb persistent — HTTP do serwera

Gdy wyzwalacz uruchamia się dla komponentu persistent, Kazzle POSTuje do serwera na zadeklarowanej path. Żądanie zawiera:
NagłówekCo ci mówi
Authorization: Bearer ${KAZZLE_TRIGGER_SECRET}Zwaliduj to. Odrzuć wywołania, które się nie zgadzają.
x-kazzle-trigger-namename wyzwalacza z manifestu.
x-kazzle-trigger-run-idNieprzezroczysty ID do korelacji logów.
x-kazzle-triggered-bycron | webhook | manual.
W przypadku wyzwalaczy webhook, oryginalna treść żądania jest przekazywana jako treść POST. W przypadku wyzwalaczy schedule treść jest pusta.
// components/events/index.ts (tryb persistent)
const TRIGGER_SECRET = process.env.KAZZLE_TRIGGER_SECRET ?? '';

Bun.serve({
  port: Number(process.env.PORT),
  hostname: process.env.HOST,
  async fetch(req) {
    const url = new URL(req.url);

    if (req.method === 'POST' && url.pathname === '/cron/daily-digest') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      await sendDigest();
      return Response.json({ ok: true });
    }

    if (req.method === 'POST' && url.pathname === '/webhook/stripe') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      const event = await req.json();
      await handleStripe(event);
      return Response.json({ ok: true });
    }

    return new Response('not found', { status: 404 });
  },
});

Tryb triggered — jednorazowo na wyzwalacz

Gdy wyzwalacz uruchamia się dla komponentu triggered, Kazzle uruchamia skrypt wejściowy od nowa i czeka na jego zakończenie. Nie ma path; skrypt dowiaduje się, który wyzwalacz się uruchomił, z zmiennych środowiskowych.
Zmienna środowiskowaWartość
TRIGGER_NAMEname wyzwalacza z manifestu.
TRIGGERED_BYcron | webhook | manual.
RUN_IDNieprzezroczysty ID do korelacji logów.
WEBHOOK_PAYLOADTreść JSON (tylko wyzwalacze webhook).
// components/events/index.ts (tryb triggered)
const trigger = process.env.TRIGGER_NAME;
const runId = process.env.RUN_ID;

if (trigger === 'daily-digest') {
  await sendDigest();
} else if (trigger === 'stripe') {
  const event = JSON.parse(process.env.WEBHOOK_PAYLOAD ?? '{}');
  await handleStripe(event);
}

console.log(`run ${runId} done`);
Komponenty triggered nie mają bezczynnych maszyn w produkcji — uruchamiają się na każde wywołanie i zamykają się przy wyjściu.

Adresy URL webhooków

POST https://api.kazzle.app/webhooks/{spaceId}/{appId}/{componentName}/{triggerName}
Segment triggerName musi odpowiadać wpisowi kind: 'webhook' w triggers[] tego komponentu. Nieznane nazwy wyzwalaczy zwracają 404.

Rozdzielczość harmonogramu

Wyrażenia cron mają 5 pól (minuta, godzina, dzień miesiąca, miesiąc, dzień tygodnia) i rozdzielczość minutowa to minimum. Harmonogramy poniżej minuty są odrzucane podczas walidacji manifestu.

Jak są rejestrowane uruchomienia

Każde uruchomienie wyzwalacza zapisuje wiersz process_runs z trigger_name, triggered_by, run_id i statusem wyjścia uruchomienia. Możesz je odpytać z własnego kodu lub sprawdzić w widoku uruchomień aplikacji.

Brak kredytów

Nieudane uruchomienie jest rejestrowane i logowane, ale harmonogram nadal działa w normalnym tempie — niestabilne uruchomienie nigdy nie wyłącza wyzwalacza. Jedyną rzeczą, która zatrzymuje uruchomienie, są kredyty: każde uruchomienie wyzwalacza jest sprawdzane względem salda Space’u, a gdy Space nie ma kredytów (lub nie ma skonfigurowanego rozliczenia), uruchomienia są pomijane z kodem 402. To się samo naprawia — harmonogram pozostaje aktywny i następne uruchomienie po uzupełnieniu kredytów działa normalnie, bez ręcznego wznowienia.

Dodawanie automatyzacji później

Prosta aplikacja może zacząć bez wyzwalaczy i zyskać je później — dodaj codzienne podsumowanie, połącz Stripe, uruchom czyszczenie. Cykl życia komponentu (processMode) i wyzwalacze (triggers[]) są niezależne, więc możesz je zmienić bez przepisywania reszty aplikacji.