Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions motomate/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { lucia } from '$lib/auth/index.js';
import type { Handle } from '@sveltejs/kit';
import { env } from '$env/dynamic/private';
import { runWorkflowChecks } from '$lib/workflow/engine.js';
import { initScheduler } from '$lib/server/scheduler.js';

initScheduler();

// Per-user timestamps to throttle passive workflow checks (in-memory, resets on server restart)
const lastWorkflowCheck = new Map<string, number>();
const WORKFLOW_CHECK_INTERVAL_MS = 60 * 60 * 1000; // 1 hour

/**
* Runtime CSRF origin validation.
* Reads PUBLIC_APP_ORIGINS at runtime so self-hosted users can configure their own origins.
Expand Down Expand Up @@ -167,15 +162,6 @@ export const handle: Handle = async ({ event, resolve }) => {
event.locals.user = user;
event.locals.session = session;

// Passive workflow check: fire at most once per hour per user, non-blocking
if (user) {
const last = lastWorkflowCheck.get(user.id) ?? 0;
if (Date.now() - last > WORKFLOW_CHECK_INTERVAL_MS) {
lastWorkflowCheck.set(user.id, Date.now());
runWorkflowChecks(user.id).catch(() => {});
}
}

const response = await resolve(event, {
transformPageChunk({ html }) {
const theme = (event.locals.user as any)?.settings?.theme;
Expand Down
11 changes: 4 additions & 7 deletions motomate/src/lib/workflow/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,8 @@ export async function runWorkflowChecks(

for (const result of results) {
if (result.trackerId) {
// Tracker-based triggers use cycle-based dedup: once any rule has fired
// for this tracker in the current service cycle, all rules are blocked
// until the user logs a service (which clears notified_by).
// This ensures exactly one notification per cycle regardless of how
// many matching rules are enabled (e.g. upcoming + overdue both on).
const notifiedBy = (result.trackerState?.notified_by ?? {}) as Record<string, string>;
if (Object.keys(notifiedBy).length > 0) continue;
if (notifiedBy[rule.id]) continue;
} else {
// Non-tracker triggers (calendar, no_odometer_update, etc.) use 23h cooldown
if (rule.last_triggered_at) {
Expand Down Expand Up @@ -287,9 +282,11 @@ export async function runWorkflowChecks(
})
.where(eq(active_trackers.id, result.trackerId));
} else {
const now = new Date().toISOString();
rule.last_triggered_at = now;
await db
.update(workflow_rules)
.set({ last_triggered_at: new Date().toISOString() })
.set({ last_triggered_at: now })
.where(eq(workflow_rules.id, rule.id));
}
}
Expand Down
Loading