Skip to content

Cu-86d2e0bc3: scheduled task hourly support#257

Merged
vizsatiz merged 3 commits into
developfrom
CU-86d2e0bc3-Scheduled-task-hourly-support
Mar 26, 2026
Merged

Cu-86d2e0bc3: scheduled task hourly support#257
vizsatiz merged 3 commits into
developfrom
CU-86d2e0bc3-Scheduled-task-hourly-support

Conversation

@vizsatiz

@vizsatiz vizsatiz commented Mar 25, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added "last_hour" date-range option for scheduled job alerts.
    • Support for a "timestamp" parameter type in dynamic queries, with automatic parsing for compatible data sources.
  • Bug Fixes

    • Scheduled email jobs now skip report/email generation when a dynamic query returns no rows.

@coderabbitai

coderabbitai Bot commented Mar 25, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a last_hour date-range option across client and server, accepts timestamp parameter type in validation and BigQuery execution, and adjusts scheduled-job runtime parameter resolution and empty-result handling.

Changes

Cohort / File(s) Summary
Client validation & types
wavefront/client/src/lib/utils.ts, wavefront/client/src/types/scheduled-job.ts
Allow parameter type: 'timestamp' in validation; extend CreateScheduledJobRequest.payload.date_range union to include 'last_hour'.
Client UI dialog
wavefront/client/src/pages/apps/.../ScheduleEmailAlertDialog.tsx
Add last_hour option to date-range selector and restore it during edit initialization; saving behavior unchanged for none.
Server scheduled job logic
wavefront/server/apps/floware/.../scheduled_job_service.py
Support last_hour in _resolve_runtime_params by computing UTC one-hour window, formatting start/end into configured param keys; log and return early when dynamic query yields no rows.
Server BigQuery datasource
wavefront/server/plugins/datasource/datasource/bigquery/__init__.py
Treat query parameters as descriptor lists; support type: 'timestamp' by parsing scheduler-style YYYY-MM-DD HH:MM:SS strings into timezone-aware UTC datetime before binding.

Sequence Diagram

sequenceDiagram
    actor User
    participant Dialog as ScheduleEmailAlertDialog
    participant Service as ScheduledJobService
    participant BigQuery as BigQueryDatasource

    User->>Dialog: choose "last_hour" and save
    Dialog->>Service: create scheduled job (date_range='last_hour')
    Service->>Service: _resolve_runtime_params() -> compute UTC now-1h to now, format params
    Service->>BigQuery: execute_dynamic_query(params)
    BigQuery->>BigQuery: for each parameter descriptor, if type=='timestamp' parse string -> UTC datetime
    BigQuery-->>Service: query results (rows)
    Service->>Service: if rows empty -> log and return
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Poem

🐰 An hour hops in, quick and bright,
Timestamps tucked in cozy light,
From dialog to job they stream,
BigQuery binds the datetime dream,
Hooray — last hour takes its flight! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'scheduled task hourly support' directly corresponds to the main change—adding 'last_hour' date range support across frontend, types, and backend services for scheduled jobs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch CU-86d2e0bc3-Scheduled-task-hourly-support

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@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.

🧹 Nitpick comments (2)
wavefront/server/plugins/datasource/datasource/bigquery/__init__.py (2)

115-123: Timestamp parsing is reasonable; consider narrowing the exception type.

The fallback to the original value on parse failure is appropriate for robustness. The static analysis flags catching bare Exception (BLE001), but this is acceptable here since strptime can raise ValueError and the fallback behavior is safe. If you want to be more explicit:

♻️ More specific exception handling
-                    except Exception:
+                    except ValueError:
                         params_to_execute[key] = value
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wavefront/server/plugins/datasource/datasource/bigquery/__init__.py` around
lines 115 - 123, Narrow the broad exception handler in the timestamp parsing
branch to only catch the expected ValueError from datetime.strptime: in the
block that checks param_types.get(key) == 'timestamp' and parses value with
datetime.strptime (the code that sets params_to_execute[key] to
value_dt.replace(tzinfo=timezone.utc) or falls back to params_to_execute[key] =
value), replace the bare except Exception with except ValueError so only parse
errors are caught and other unexpected exceptions still surface.

96-101: Redundant isinstance check.

On line 98, isinstance(params, dict) is always true because line 95's list comprehension [params['name'] for params in query_params] would already fail if items weren't dicts. Consider simplifying:

♻️ Simplified param_types extraction
             param_types = {
-                params['name']: (
-                    params.get('type') if isinstance(params, dict) else None
-                )
+                params['name']: params.get('type')
                 for params in query_params
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wavefront/server/plugins/datasource/datasource/bigquery/__init__.py` around
lines 96 - 101, The comprehension that builds param_types uses an unnecessary
isinstance(params, dict) check because query_params items must be dicts (the
earlier comprehension accessing params['name'] would have failed otherwise);
simplify the comprehension for param_types by removing the isinstance guard and
directly use params.get('type') (i.e., change the dict comprehension that
assigns to param_types to rely on params.get('type') for each params in
query_params).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@wavefront/server/plugins/datasource/datasource/bigquery/__init__.py`:
- Around line 115-123: Narrow the broad exception handler in the timestamp
parsing branch to only catch the expected ValueError from datetime.strptime: in
the block that checks param_types.get(key) == 'timestamp' and parses value with
datetime.strptime (the code that sets params_to_execute[key] to
value_dt.replace(tzinfo=timezone.utc) or falls back to params_to_execute[key] =
value), replace the bare except Exception with except ValueError so only parse
errors are caught and other unexpected exceptions still surface.
- Around line 96-101: The comprehension that builds param_types uses an
unnecessary isinstance(params, dict) check because query_params items must be
dicts (the earlier comprehension accessing params['name'] would have failed
otherwise); simplify the comprehension for param_types by removing the
isinstance guard and directly use params.get('type') (i.e., change the dict
comprehension that assigns to param_types to rely on params.get('type') for each
params in query_params).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3ee9277d-fd24-4b5c-bf1a-7ccf371a7068

📥 Commits

Reviewing files that changed from the base of the PR and between c1e1cc8 and 08a7a79.

📒 Files selected for processing (5)
  • wavefront/client/src/lib/utils.ts
  • wavefront/client/src/pages/apps/[appId]/datasources/ScheduleEmailAlertDialog.tsx
  • wavefront/client/src/types/scheduled-job.ts
  • wavefront/server/apps/floware/floware/services/scheduled_job_service.py
  • wavefront/server/plugins/datasource/datasource/bigquery/__init__.py

@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.

🧹 Nitpick comments (1)
wavefront/server/apps/floware/floware/services/scheduled_job_service.py (1)

405-424: Dead code after early return.

After the early return at line 415 when rows is empty, the if rows: check at line 417 is always true, making lines 423-424 unreachable.

♻️ Suggested simplification
         if len(rows) == 0:
             start_key = str(payload.get('start_date_param', 'start_date'))
             end_key = str(payload.get('end_date_param', 'end_date'))
             applied_start = params.get(start_key) if isinstance(params, dict) else None
             applied_end = params.get(end_key) if isinstance(params, dict) else None
             logger.info(
                 f'No records in scheduled window for query_id={query_id}; '
                 f'applying range {applied_start}..{applied_end} (keys: {start_key}, {end_key}). '
                 'Skipping email.'
             )
             return

-        if rows:
-            fieldnames = list(rows[0].keys())
-            for row in rows[1:]:
-                for k in row:
-                    if k not in fieldnames:
-                        fieldnames.append(k)
-        else:
-            fieldnames = []
+        fieldnames = list(rows[0].keys())
+        for row in rows[1:]:
+            for k in row:
+                if k not in fieldnames:
+                    fieldnames.append(k)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wavefront/server/apps/floware/floware/services/scheduled_job_service.py`
around lines 405 - 424, The code has an early return when len(rows) == 0, so the
subsequent conditional "if rows: ... else: fieldnames = []" is dead/ redundant;
remove the else branch and simplify by directly computing fieldnames =
list(rows[0].keys()) and merging any additional keys from remaining rows (loop
over rows[1:]) since at that point rows is guaranteed non-empty; update the
block containing rows, fieldnames, and the for-loops (referenced symbols: rows,
fieldnames, payload, params, query_id in scheduled_job_service.py) to remove the
unreachable "else: fieldnames = []" branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@wavefront/server/apps/floware/floware/services/scheduled_job_service.py`:
- Around line 405-424: The code has an early return when len(rows) == 0, so the
subsequent conditional "if rows: ... else: fieldnames = []" is dead/ redundant;
remove the else branch and simplify by directly computing fieldnames =
list(rows[0].keys()) and merging any additional keys from remaining rows (loop
over rows[1:]) since at that point rows is guaranteed non-empty; update the
block containing rows, fieldnames, and the for-loops (referenced symbols: rows,
fieldnames, payload, params, query_id in scheduled_job_service.py) to remove the
unreachable "else: fieldnames = []" branch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d05c4bb4-b5bd-4ecc-ada8-a67d72b8266f

📥 Commits

Reviewing files that changed from the base of the PR and between 08a7a79 and 3b46001.

📒 Files selected for processing (1)
  • wavefront/server/apps/floware/floware/services/scheduled_job_service.py

@vizsatiz vizsatiz merged commit 90760a1 into develop Mar 26, 2026
10 checks passed
@vizsatiz vizsatiz deleted the CU-86d2e0bc3-Scheduled-task-hourly-support branch March 26, 2026 07:21
thomastomy5 pushed a commit that referenced this pull request Apr 27, 2026
* fix(floware): for supporting scheduled jobs with hourly data query

* Adding support for last hour

* Dont send email if no records in db
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