ServiceProviderJobNotifier - Project Overview
Solution Structure
| Project |
Type |
Framework |
Description |
| TELS.ServiceProviderJobNotifier |
Console App (Batch) |
.NET 8.0 |
Scheduled batch job — publishes service provider notification commands |
| TELS.ServiceProviderJobNotifier.Tests |
xUnit (.NET 8.0) |
.NET 8.0 |
Unit tests (Moq, xUnit) |
Architecture
Purpose
ServiceProviderJobNotifier is a scheduled Nomad batch job that publishes notification commands to service providers about contracted service tasks. It is a satellite service to the main Contracted Services system. The notifier runs on multiple cron schedules throughout each month to trigger 5 different notification types.
How It Works
- Validates the current date is a valid business day for the notice type (unless
IgnoreDateRestrictions=true)
- Retrieves distinct active service providers from the Contracted Services API (paginated)
- Filters out blacklisted service providers using Platform settings
- Publishes a notification command per non-blacklisted service provider via BusProxy
- The main Contracted Services subscriber consumes these commands and sends actual emails via AWS SES
Notice Types & Schedules
| Notice Type |
Cron Schedule |
Description |
| FirstNotice |
0 6 10-15 * 1-5 |
Monthly tickets summary (1st business day on/after 10th) |
| SecondNotice |
0 6 17-22 * 1-5 |
Follow-up monthly tickets (1st business day on/after 17th) |
| MarkJobsAsComplete |
0 8 * * 1-5 |
Daily jobs needing completion |
| NewTickets |
0 6 * * 1-5 |
Daily new tickets notification |
| MissingDocumentationNotice |
0 6 * * 1-5 |
Daily missing documentation reminder |
On-demand variants exist for FirstNotice and SecondNotice with IgnoreDateRestrictions=true (cron: * * * * * 1979 — never auto-runs).
Published Messages
| Message Type |
Consumed By |
ServiceProviderMonthlyContractedServiceTicketsNotificationCommand |
Contracted Services subscriber |
ServiceProviderFollowupMonthlyContractedServiceTicketsNotificationCommand |
Contracted Services subscriber |
ServiceProviderMonthlyJobsNeedingCompletionCommand |
Contracted Services subscriber |
ServiceProviderDailyNewTicketsNotificationCommand |
Contracted Services subscriber |
ServiceProviderDailyJobsNeedingDocumentation |
Contracted Services subscriber |
All messages are published via BusProxy (TELS.BusProxy.Client 3.0.0 with S3 fallback).
Key Technology Stack
| Category |
Technology |
| Runtime |
.NET 8.0 |
| Orchestration |
Nomad (Platypus framework) |
| Event Publishing |
TELS.BusProxy.Client 3.0.0 + S3 fallback |
| Auth |
JWT token refresh via Auth Service |
| Resilience |
Polly (HTTP retry with exponential backoff) |
| Configuration |
Vault (secrets) + Consul (config) via envconsul |
| Monitoring |
New Relic + PagerDuty alerting |
| Logging |
JSON to AWS CloudWatch (platypus log group) |
| Testing |
xUnit 2.9.3, Moq 4.20.72 |
External Dependencies
| Integration |
Mechanism |
Description |
| Contracted Services API |
HTTP (TELS.WebServiceClients.ContractedServices.V2 2.6.1) |
Retrieves active contracts and service providers |
| Building Services API |
HTTP (TELS.WebServiceClients.BuildingServices.V1 5.4.0) |
Business day calculations |
| Platform Service |
HTTP (TELS.Platform.ClientSdk 1.1.0) |
Service provider blacklist settings |
| Auth Service |
HTTP |
Token refresh (5-minute cache) |
| BusProxy |
HTTP + S3 fallback |
Message publishing (45s timeout) |
Deployment
Infrastructure
- Platform: Nomad batch jobs on AWS (us-east-1)
- Container:
tels/contracted-services/serviceproviderjobnotifier
- Resources: 100 MHz CPU, 300 MB memory
- IaC: Terraform (nomad-batch module v2)
- Secrets: HashiCorp Vault (
secrets/tels/service-provider-job-notifier)
- Config: Consul (
tels/service-provider-job-notifier)
Environments
| Environment |
Nomad Dashboard |
| DEV |
https://nomad.directsupply-sandbox.cloud/ui/jobs/tels-service-provider-job-notifier |
| QA |
https://nomad.directsupply-testing.cloud/ui/jobs/tels-service-provider-job-notifier |
| PROD |
https://nomad.directsupply.cloud/ui/jobs/tels-service-provider-job-notifier |
Notes
- No database: Purely API-driven batch job with no direct database access.
- No API endpoints: Console application only — not a web service.
- No MQ consumers: Publishes messages only — does not consume any.
- Business day validation: Uses BuildingServices API to calculate business days, respecting weekends and holidays.
- Blacklist filtering: Reads Platform settings to exclude service providers from communications.
- Generated from template: Created via
generator-nomad v1.0.320 scaffolding tool.