Skip to content

chore: tasks rework#88

Merged
hmbanan666 merged 1 commit into
mainfrom
chore
Aug 22, 2025
Merged

chore: tasks rework#88
hmbanan666 merged 1 commit into
mainfrom
chore

Conversation

@hmbanan666

@hmbanan666 hmbanan666 commented Aug 22, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added a configurable AI daily report prompt via environment/config (NUXT_AI_DAILY_REPORT_PROMPT).
  • Chores
    • Background tasks now run only in production, with clear skip logs in non-production (daily report, kitchen averages, ratings, revenue, and auto-create).
  • Documentation
    • Updated example environment file to include NUXT_AI_DAILY_REPORT_PROMPT.

@hmbanan666 hmbanan666 self-assigned this Aug 22, 2025
@coderabbitai

coderabbitai Bot commented Aug 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a configurable AI daily report prompt to runtime config and .env example. Introduces production-only guards with logging across several scheduled tasks, skipping execution outside production. The daily-report task now uses the configurable prompt. No public API surface changes beyond the new config key.

Changes

Cohort / File(s) Summary of Changes
Config: AI runtime & env sample
apps/web-app/nuxt.config.ts, apps/web-app/.env.example
Added runtimeConfig.ai.dailyReportPrompt (default empty string) and corresponding NUXT_AI_DAILY_REPORT_PROMPT= placeholder in env example.
AI daily report task
apps/web-app/server/tasks/ai/daily-report.ts
Added production-only guard with logger; imported node:process; replaced hard-coded system prompt with ai.dailyReportPrompt.
Kitchen tasks: production guards
apps/web-app/server/tasks/kitchen/average-update.ts, apps/web-app/server/tasks/kitchen/rating-update.ts, apps/web-app/server/tasks/kitchen/revenue-update.ts
Added node:process import and production-only guards with skip logging; main logic unchanged and now bypassed outside production.
Task auto-create: production guard
apps/web-app/server/tasks/task/auto-create.ts
Added node:process import and production-only guard with skip logging; skips pre-delay and main logic outside production.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Cron as Scheduler
  participant Task as Task Runner
  participant Env as process.env
  participant Log as Logger

  Cron->>Task: run()
  Task->>Env: Read NODE_ENV
  alt NODE_ENV !== "production"
    Task->>Log: info("Skipping task in non-production environment")
    Task-->>Cron: { result: true }
  else production
    Task->>Task: Execute existing task logic
    Task-->>Cron: { result: true }
  end
Loading
sequenceDiagram
  autonumber
  actor Cron as Scheduler
  participant Daily as daily-report.ts
  participant Config as runtimeConfig.ai
  participant OpenAI as AI Client
  participant TG as Telegram

  Cron->>Daily: run()
  Daily->>Config: get dailyReportPrompt
  Daily->>Daily: collect completed tasks
  Daily->>OpenAI: create message (system: dailyReportPrompt)
  OpenAI-->>Daily: response
  Daily->>TG: send final message
  Daily-->>Cron: { result: true }
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • chore: removed old libs #36 — Also changes kitchen average-update task logic; likely intersects with the new production guard in the same file.

Poem

I twitch an ear at cron’s soft chime,
In prod I hop, in dev I bide my time.
A prompt now whispers what reports should say,
I nibble config, then send away.
Logs like footprints in morning dew—
Skip, skip, hop—only when it’s due. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/web-app/server/tasks/kitchen/revenue-update.ts (1)

21-31: Critical Fix Required: Compute True UTC Week Bounds & Confirm Inclusive End Date

  • The current code’s comment “use UTC+0 timezone” is misleading. date-fns’ startOfWeek/endOfWeek always operate in the system’s local time zone; shifting the Date by getTimezoneOffset doesn’t change that (runebook.dev).
  • The repository method listRevenuesByKitchenForPeriod uses a <= date(end) comparison, so the end date is already treated as inclusive (en.wikipedia.org). There’s no need to push the boundary to the next Monday for exclusivity.

Apply the following diff to compute exact UTC week boundaries and simplify end-date handling:

-      // From this monday to sunday (use UTC+0 time zone)
-      const now = new Date()
-      const utcNow = new Date(now.getTime() + now.getTimezoneOffset() * 60000)
-
-      const thisMonday = startOfWeek(utcNow, { weekStartsOn: 1 })
-      const thisSunday = endOfWeek(utcNow, { weekStartsOn: 1 })
-
-      // Previous week
-      const utcWeekAgo = new Date(utcNow.getTime() - 7 * 24 * 60 * 60 * 1000)
-      const prevMonday = startOfWeek(utcWeekAgo, { weekStartsOn: 1 })
-      const prevSunday = endOfWeek(utcWeekAgo, { weekStartsOn: 1 })
+      // From this Monday to Sunday (UTC)
+      const now = new Date()
+      const day = (now.getUTCDay() + 6) % 7                // Mon=0 … Sun=6
+      const thisMonday = new Date(Date.UTC(
+        now.getUTCFullYear(),
+        now.getUTCMonth(),
+        now.getUTCDate() - day,
+        0, 0, 0, 0
+      ))
+      const thisSunday = new Date(Date.UTC(
+        thisMonday.getUTCFullYear(),
+        thisMonday.getUTCMonth(),
+        thisMonday.getUTCDate() + 6,
+        23, 59, 59, 999
+      ))
+
+      // Previous week (UTC)
+      const prevMonday = new Date(Date.UTC(
+        thisMonday.getUTCFullYear(),
+        thisMonday.getUTCMonth(),
+        thisMonday.getUTCDate() - 7,
+        0, 0, 0, 0
+      ))
+      const prevSunday = new Date(Date.UTC(
+        prevMonday.getUTCFullYear(),
+        prevMonday.getUTCMonth(),
+        prevMonday.getUTCDate() + 6,
+        23, 59, 59, 999
+      ))
apps/web-app/server/tasks/kitchen/rating-update.ts (1)

21-26: Guard against empty points to avoid “reduce of empty array” and NaN updates.

If no points pass the filter, reduce() will throw, and even if it didn’t, dividing by zero would produce NaN.

Apply this diff:

-        const points = kitchen.feedbackPoints.filter((point) => point.rating > 0 && point.reviews >= 5)
-        const rawRating = points.reduce((acc, point) => acc + point.rating, 0) / points.length
+        const points = kitchen.feedbackPoints.filter((point) => point.rating > 0 && point.reviews >= 5)
+        if (points.length === 0) {
+          continue
+        }
+        const rawRating = points.reduce((acc, point) => acc + point.rating, 0) / points.length

Consider weighting by reviews (sum(rating*reviews)/sum(reviews)) if that better reflects quality.

🧹 Nitpick comments (13)
apps/web-app/.env.example (2)

23-23: Fix dotenv-linter UnorderedKey: place the new key before MODEL (keep AI keys alphabetized).

The linter expects keys to be ordered. Move NUXT_AI_DAILY_REPORT_PROMPT above NUXT_AI_MODEL to keep the AI block sorted.

Apply this diff within the AI section:

 # AI
 NUXT_AI_API_KEY=
 NUXT_AI_BASE_URL=
+NUXT_AI_DAILY_REPORT_PROMPT=
-NUXT_AI_MODEL=
-NUXT_AI_MODEL_PRO=
-NUXT_AI_SERVICE_TOKEN=
+NUXT_AI_MODEL=
+NUXT_AI_MODEL_PRO=
+NUXT_AI_SERVICE_TOKEN=

23-24: Clarify multiline prompt usage in .env.

If the daily-report prompt is multi-line, .env doesn’t handle raw newlines. Consider documenting escaping (e.g., \n) or adding an alternate “_FILE” variant (NUXT_AI_DAILY_REPORT_PROMPT_FILE) that loads the prompt from a file.

I can add a small helper in nuxt.config.ts to read NUXT_AI_DAILY_REPORT_PROMPT_FILE when present and fall back to NUXT_AI_DAILY_REPORT_PROMPT.

apps/web-app/server/tasks/kitchen/revenue-update.ts (2)

34-38: Fetch week and previous-week revenues concurrently per kitchen.

Two independent DB calls can be parallelized to reduce latency.

Apply this diff:

-        const revenuesThisWeek = await repository.kitchen.listRevenuesByKitchenForPeriod(kitchen.id, thisMonday, thisSunday)
-        const revenuesPrevWeek = await repository.kitchen.listRevenuesByKitchenForPeriod(kitchen.id, prevMonday, prevSunday)
+        const [revenuesThisWeek, revenuesPrevWeek] = await Promise.all([
+          repository.kitchen.listRevenuesByKitchenForPeriod(kitchen.id, thisMonday, thisSunday),
+          repository.kitchen.listRevenuesByKitchenForPeriod(kitchen.id, prevMonday, prevSunday),
+        ])

49-50: Make the update log actionable or switch to debug.

The commented logger line won’t help in prod incidents. Either enable it at debug level or remove it.

-        // logger.log(`Kitchen ${kitchen.id}: Revenue updated from ${kitchen.revenueForThisWeek} to ${revenueForThisWeek}`)
+        // logger.debug(`Kitchen ${kitchen.id}: Revenue updated from ${kitchen.revenueForThisWeek} to ${revenueForThisWeek}`)
apps/web-app/server/tasks/task/auto-create.ts (3)

31-31: Date uses UTC midnight; verify intended timezone.

toISOString().split('T')[0] yields a UTC date. If “days from now” should be local-calendar based, prefer formatting in local tz.

-        const date = creator.templateDate ? new Date(new Date().getTime() + Number(creator.templateDate) * 24 * 60 * 60 * 1000).toISOString().split('T')[0] : null
+        // If the date must be in local calendar (yyyy-MM-dd):
+        const localNow = new Date(Date.now() + Number(creator.templateDate) * 24 * 60 * 60 * 1000)
+        const date = creator.templateDate
+          ? `${localNow.getFullYear()}-${String(localNow.getMonth() + 1).padStart(2, '0')}-${String(localNow.getDate()).padStart(2, '0')}`
+          : null

Alternatively, use date-fns format(localNow, 'yyyy-MM-dd') if available.


51-71: Naive cron parsing; consider a parser or broaden support.

Only exact numeric values or '' are supported; no ranges (1-5), lists (1,3,5), or steps (/5). That can surprise operators.

I can wire up cron-parser (no runtime overhead off-schedule) or extend isCronDue to support common patterns while keeping zero deps.


51-62: Unify language in comments.

Comments are partially in Russian; consider English for consistency across the repo.

apps/web-app/server/tasks/kitchen/average-update.ts (2)

13-16: Production guard looks good.

Matches the PR pattern. Minor style nit: in this file the guard is inside try/catch while auto-create places it before try. Consider standardizing placement across tasks.


20-33: Potential throughput improvement: batch updates or parallelize per metric.

Per-metric DB calls are sequential; if metrics is large, this will be slow.

Sketch:

  • Gather all totals/checks first using Promise.all.
  • Use a bulk update if repository supports it, otherwise parallelize with a sane concurrency limit (e.g., p-limit 5).

I can provide a p-limit based refactor if desired.

apps/web-app/server/tasks/kitchen/rating-update.ts (1)

34-35: Use consistent log level.

Other tasks use info; prefer logger.info for parity and to honor log-level filtering.

-        logger.log(`Kitchen ${kitchen.id}: Rating updated from ${kitchen.rating} to ${updatedRating}`)
+        logger.info(`Kitchen ${kitchen.id}: Rating updated from ${kitchen.rating} to ${updatedRating}`)
apps/web-app/server/tasks/ai/daily-report.ts (3)

1-1: Importing process is unnecessary in Node/Nitro contexts.

process is globally available; keep it simple and drop the import.

Apply this diff:

-import process from 'node:process'

14-17: Production-only guard: prefer lower log level and explicit skip signal.

Reduce log noise and make the outcome machine-readable with a skipped flag.

Apply this diff:

-    if (process.env.NODE_ENV !== 'production') {
-      logger.info('Skipping task in non-production environment')
-      return { result: true }
-    }
+    if (process.env.NODE_ENV !== 'production') {
+      logger.debug(`Skipping ai:daily-report in ${process.env.NODE_ENV} environment`)
+      return { result: true, skipped: true }
+    }

Confirm that any upstream task runner/metrics ingestion handles an extra skipped: true field without breaking dashboards.


35-47: Guard against empty system prompt and add model fallback.

If ai.dailyReportPrompt is unset/blank (empty default in config), the system message becomes empty, which degrades output quality. Also, fall back to ai.model when ai.modelPro isn’t configured.

Apply this diff:

-      const response = await client.chat.completions.create({
-        model: ai.modelPro,
-        messages: [
-          {
-            role: 'system',
-            content: ai.dailyReportPrompt,
-          },
-          {
-            role: 'user',
-            content: JSON.stringify(preparedTasks),
-          },
-        ],
-      })
+      const systemPrompt = (ai.dailyReportPrompt || '').trim()
+      const messages = [
+        ...(systemPrompt ? [{ role: 'system' as const, content: systemPrompt }] : []),
+        { role: 'user' as const, content: JSON.stringify(preparedTasks) },
+      ]
+      const response = await client.chat.completions.create({
+        model: ai.modelPro || ai.model,
+        messages,
+      })

Optionally, warn when the prompt is missing so it’s visible in logs:

if (!systemPrompt) logger.warn('ai.dailyReportPrompt is empty; sending request without system instruction')
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 75e24b9 and bfe59a4.

📒 Files selected for processing (7)
  • apps/web-app/.env.example (1 hunks)
  • apps/web-app/nuxt.config.ts (1 hunks)
  • apps/web-app/server/tasks/ai/daily-report.ts (2 hunks)
  • apps/web-app/server/tasks/kitchen/average-update.ts (1 hunks)
  • apps/web-app/server/tasks/kitchen/rating-update.ts (2 hunks)
  • apps/web-app/server/tasks/kitchen/revenue-update.ts (1 hunks)
  • apps/web-app/server/tasks/task/auto-create.ts (2 hunks)
🧰 Additional context used
🪛 dotenv-linter (3.3.0)
apps/web-app/.env.example

[warning] 23-23: [UnorderedKey] The NUXT_AI_DAILY_REPORT_PROMPT key should go before the NUXT_AI_MODEL key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (4)
apps/web-app/server/tasks/kitchen/revenue-update.ts (1)

14-17: Production guard is correct and in the right place.

Early exit prevents accidental data churn in non-prod. Consistent with the PR’s pattern.

apps/web-app/server/tasks/task/auto-create.ts (1)

12-15: Production guard placement LGTM.

Skip happens before any delay or I/O—good.

apps/web-app/server/tasks/kitchen/rating-update.ts (1)

13-16: Production guard is correct.

Early exit mirrors other tasks and avoids unnecessary DB work in non-prod.

apps/web-app/server/tasks/ai/daily-report.ts (1)

6-6: Dedicated logger looks good.

Naming/tagging the logger for this task improves traceability. No changes needed.

baseUrl: '',
apiKey: '',
serviceToken: '',
dailyReportPrompt: '',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Good addition; server-only placement is correct.

Adding ai.dailyReportPrompt under runtimeConfig (server-side) avoids leaking prompt text to the client. One follow-up: because it defaults to an empty string, make sure the task guards against empty/whitespace prompts (see task review).

If not already done, ensure .env.example includes the matching key and casing:


🏁 Script executed:

#!/bin/bash
# Verify example env contains the new key
rg -n --line-number -C1 '^NUXT_AI_DAILY_REPORT_PROMPT=' apps/web-app/.env.example

Length of output: 145


Verify .env.example and enforce non-empty dailyReportPrompt

  • ✅ Confirmed that NUXT_AI_DAILY_REPORT_PROMPT is defined in apps/web-app/.env.example (line 23).
  • ⚠️ Please add validation around runtimeConfig.ai.dailyReportPrompt to ensure it isn’t empty or whitespace-only (e.g. throw a clear error or fallback to a safe default) before sending it to the AI.
🤖 Prompt for AI Agents
In apps/web-app/nuxt.config.ts around line 21,
runtimeConfig.ai.dailyReportPrompt is currently allowed to be empty; add a
validation step during config/build initialization to trim the value and ensure
it is not empty or whitespace-only, and if it is invalid either throw a clear
error (with guidance to set NUXT_AI_DAILY_REPORT_PROMPT) or assign a safe
default prompt before any code sends it to the AI; implement the check where
runtimeConfig is constructed so downstream consumers always receive a validated,
non-empty string.

@hmbanan666 hmbanan666 merged commit 42ee807 into main Aug 22, 2025
8 checks passed
@hmbanan666 hmbanan666 deleted the chore branch August 22, 2025 07:43
@coderabbitai coderabbitai Bot mentioned this pull request Sep 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant