Skip to content

feat(notifications): add scheduler service for time-based due-date al… - #388

Open
Teeeyanaa wants to merge 2 commits into
Invoice-Liquidity-Network:mainfrom
Teeeyanaa:feat/notifications-scheduler
Open

feat(notifications): add scheduler service for time-based due-date al…#388
Teeeyanaa wants to merge 2 commits into
Invoice-Liquidity-Network:mainfrom
Teeeyanaa:feat/notifications-scheduler

Conversation

@Teeeyanaa

@Teeeyanaa Teeeyanaa commented Jun 30, 2026

Copy link
Copy Markdown

…erts

Closes #379

Adds SchedulerService that runs every 30 minutes (node-cron) and sends invoice.expiring_soon email reminders at the 72-hour and 24-hour thresholds before an invoice due date.

Key implementation details:

  • Queries the invoice DB for status='Funded' rows whose due_date falls within the respective threshold window
  • Delivers reminders to all active email subscribers matching the invoice's freelancer, payer, and funder addresses
  • Idempotency enforced via a delivered_reminders table (PK: invoice_id + threshold_h) in the notifications DB, preventing duplicate sends across restarts and repeated cron firings
  • Exposes initDeliveredRemindersSchema() for schema migration
  • Accepts an injectable clock (now option) for deterministic tests
  • Configurable cron expression (default: */30 * * * *)

Also fixes a pre-existing broken tsconfig.json extends path (../../tsconfig.base.json → ../tsconfig.base.json).

Tests (22 cases):

  • Schema creation and idempotency
  • 72 h and 24 h reminder delivery
  • Correct filtering of non-Funded, out-of-window, inactive, unsubscribed, and wrong-eventType subscribers
  • Wildcard (*) eventType matching
  • Notifications sent to all three roles (freelancer, payer, funder)
  • Idempotency: second run is a no-op, persists across separate SchedulerService instances, records separate rows per threshold, writes idempotency record even when email delivery fails
  • Lifecycle: start/stop, custom cron expression
  • Logging assertions

Summary

Package Affected

  • SDK (@iln/sdk)
  • CLI (@iln/cli)
  • Indexer (@iln/indexer)
  • Notifications
  • Smart Contracts (invoice_liquidity, iln_governance, iln_distribution, reputation_bonus)
  • E2E Tests
  • Documentation
  • CI/CD

Related Issue

Closes #

Complexity

  • Trivial (typo, docs, small refactor)
  • Medium (new feature, bug fix)
  • High (major refactor, breaking change, security-critical)

Changes Made

Changeset Included

  • Yes
  • No (not needed for this change)

Test Evidence

# Example:
# cargo test
# running 15 tests
# test result: ok. 15 passed; 0 failed
Test output

Breaking Change

  • Yes (migration notes below)
  • No

Migration Notes

Security Considerations

Checklist

  • Code follows project conventions (see CONTRIBUTING.md)
  • Tests added/updated and passing
  • Documentation updated (if needed)
  • Commit message follows Conventional Commits
  • No secrets or sensitive data in code
  • Breaking changes documented (if applicable)
  • Changeset added (if needed for release)

Closes #379

…erts

Closes Invoice-Liquidity-Network#379

Adds SchedulerService that runs every 30 minutes (node-cron) and sends
invoice.expiring_soon email reminders at the 72-hour and 24-hour
thresholds before an invoice due date.

Key implementation details:
- Queries the invoice DB for status='Funded' rows whose due_date falls
  within the respective threshold window
- Delivers reminders to all active email subscribers matching the
  invoice's freelancer, payer, and funder addresses
- Idempotency enforced via a delivered_reminders table
  (PK: invoice_id + threshold_h) in the notifications DB, preventing
  duplicate sends across restarts and repeated cron firings
- Exposes initDeliveredRemindersSchema() for schema migration
- Accepts an injectable clock (now option) for deterministic tests
- Configurable cron expression (default: */30 * * * *)

Also fixes a pre-existing broken tsconfig.json extends path
(../../tsconfig.base.json → ../tsconfig.base.json).

Tests (22 cases):
- Schema creation and idempotency
- 72 h and 24 h reminder delivery
- Correct filtering of non-Funded, out-of-window, inactive,
  unsubscribed, and wrong-eventType subscribers
- Wildcard (*) eventType matching
- Notifications sent to all three roles (freelancer, payer, funder)
- Idempotency: second run is a no-op, persists across separate
  SchedulerService instances, records separate rows per threshold,
  writes idempotency record even when email delivery fails
- Lifecycle: start/stop, custom cron expression
- Logging assertions
@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@Teeeyanaa Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Nursca

Nursca commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Please fix merge conflicts @Teeeyanaa

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.

Add notifications/src/services/schedulerService.ts for time-based alerts

2 participants