Hodor (SQL Server — dmorders_thompson)#
Purpose: Prospect / order-side contact data (IPv4). Reads for identity; update intents are emitted as a Prospect Import deliverable, and in live mode the action engine also applies a targeted AutoRenewal SQL update for INACTIVE determinations.
Code: src/auto_responder/services/databases/hodor.py
Configuration#
| Setting | Notes |
|---|---|
HODOR_CONNECTION_STRING | Full ODBC/SQL connection string (preferred when you already have one). |
HODOR_DB_HOST, HODOR_DB_DATABASE, HODOR_DB_USER, HODOR_DB_PASSWORD, HODOR_DB_PORT | Built into a connection string when HODOR_CONNECTION_STRING is unset. Default database name in config is dmorders_thompson. |
HODOR_* column/table overrides | Optional: hodor_contact_table, hodor_id_column, hodor_email_column, etc. — for schema differences (see config.py). |
HODOR_AUTOMATIC_UPDATES | When true (default) and writes are enabled, INACTIVE handling also applies the AutoRenewal SQL (IsNoLongerWithFirm = 1, LastUpdatedDate = getdate(), UpdatedReason = 'Updated based on AutoRenewal Program') by email in addition to queuing Prospect Import rows. When false, only Prospect Import rows are queued. |
NOTIFICATION_EMAIL_VENU | Recipient for Hodor Prospect Import digest emails. If unset, NOTIFICATION_EMAIL_VENU is used. |
If no Hodor SQL configuration is present, the connector runs in graceful-unavailable mode (available=False): lookups return empty, writes no-op.
Contact lookup#
| Call | Purpose |
|---|---|
lookup_by_email | Per-email lookup |
lookup_batch | Optional batch path in ContactLookup.lookup_batch when available and the method exists |
Action engine touches#
The action engine queues Prospect Import rows and sends notify_hodor_prospect_import (catalog N01) at batch flush with hodor_prospect_import_verification.csv (InboxSource, Action, RequestedStatus, and full SAC columns). See NOTIFICATIONS_CATALOG — N01.
In live mode with HODOR_AUTOMATIC_UPDATES=true, INACTIVE determinations may also call mark_inactive_by_email_for_autorenewal(email) to set AutoRenewal flags directly in Hodor.
Hodor email/title updates follow the same CUPOLA active-only gate as other systems: if the preferred CUPOLA row is missing or inactive, updates are not queued and the case goes to Human Review.
INACTIVE (_handle_inactive)#
| Call / behavior | Purpose |
|---|---|
Prospect Import row (Action=status, RequestedStatus=INACTIVE) | Queue inactive request for Hodor ingestion |
mark_inactive_by_email_for_autorenewal(email) (live mode, HODOR_AUTOMATIC_UPDATES=true) | Apply AutoRenewal update: IsNoLongerWithFirm = 1, LastUpdatedDate = getdate(), UpdatedReason = 'Updated based on AutoRenewal Program' for the sender email |
check_active_subscription(id) | If true, include Hodor in "systems with subscription" notification list (read-only; always runs when Hodor is available) |
ACTIVE (_handle_active)#
After Cupola / Salesforce branches, remaining systems (including Hodor) use:
| Call / behavior | Purpose |
|---|---|
Prospect Import row (Action=status, RequestedStatus=ACTIVE) | Queue active request when Hodor row is inactive. Note: this does not auto-reactivate CUPOLA; CUPOLA reactivation remains manual-review only. |
OUT_OF_OFFICE#
OOO determinations are routed to _handle_out_of_office and add a Human Review row (HUMAN_REVIEW_REASON_OUT_OF_OFFICE). No Hodor calls fire — neither live SQL nor the manual-mode pending-actions queue.
Changed email / title (shared handler)#
Runs only when the CUPOLA active-only gate in _handle_title_update passes. After the gate:
- Multipub records are skipped in the record loop (marketing-owned).
- For Hodor, email/title updates are queued as Prospect Import rows (
Action=email/Action=title). - If the CUPOLA gate fails (no CUPOLA row or inactive), Hodor updates are not queued and not executed — the whole row goes to Human Review.
REPLACEMENT (_handle_replacement)#
Does not insert a new Hodor row in code (add_contact returns None in the connector).
Uses read helpers for deliverable lists when implemented:
| Call | Purpose |
|---|---|
get_library_for_account(account) | Alternate-contact output — library hint |
generate_import_record(...) | Alternate-contact output — suggested import payload |
Connector capabilities worth knowing#
update_contact_status,update_contact_email: connector methods exist but action routing normally emits Prospect Import rows instead of calling them.mark_inactive_by_email_for_autorenewal(email): used by_handle_inactivein live mode whenHODOR_AUTOMATIC_UPDATES=trueto apply the AutoRenewal inactivation SQL by email.add_contact: not implemented (logs and returnsNone)check_active_subscription: queries optional subscription tables if present in schema
Read-only / dry-run behavior#
Application behavior: ActionEngine always emits Prospect Import rows and emails them to Venu (NOTIFICATION_EMAIL_VENU, catalog N01). In live mode (writes enabled, HODOR_AUTOMATIC_UPDATES=true), INACTIVE handling also issues a targeted Hodor UPDATE by email via mark_inactive_by_email_for_autorenewal.
Simulation — no writes (WRITE_OPERATIONS_ENABLED=false): When Hodor SQL is configured and hodor_real.available, main.py wraps the connector with ReadOnlyDatabaseWrapper like Cupola/Multipub/Salesforce — writes are logged and not executed. If Hodor is not configured, the connector stays graceful-unavailable (no wrapper needed).
Dev mock-all (MOCK_ALL_SERVICES_FOR_DEV=true): main.py constructs a real HodorDatabase while Cupola/Multipub/Salesforce use mocks. Step 4c contact lookup is skipped in dry-run (main.py uses a minimal stub Contact), so routine per-email Hodor lookups do not run; the Hodor instance is still present for any code paths that reference it. If SQL credentials are set, be aware of the connector’s behavior vs mocks for other systems. If SQL is not configured, Hodor stays graceful-unavailable.
Output artifacts#
Hodor ProsNums appear on inactive, alternate, undeliverable deliverables via OutputDocumentCollector.
Related#
- cupola.html — IPv4 org/person parallel
- README.html — mode matrix