Project Challenges
Key technical hurdles overcome during the development of Job-Easy.
1. The "Orphaned Audit Log" Problem
Problem: When an admin deletes a user or a company, standard database CASCADE deletes remove all child rows. But the AuditLog and EmailLog tables reference these entities to display their history. If the entity is gone, the log vanishes or breaks, violating compliance requirements.
Solution: Converted the foreign keys to SetNull rather than Cascade, and altered the logging infrastructure to take hard static snapshots (e.g. saving the string name of the template or company) at the moment the log is created. The audit trail persists intelligibly even when the referenced entity is destroyed.
2. Serverless Execution Black-Holes
Problem: Serverless platforms unceremoniously kill functions when they exceed their maximum execution duration (e.g. 60 seconds). Because the process is externally terminated, a standard try/catch block cannot catch the termination to record a "failed" state in the database, leaving the cron job stuck in a "running" state indefinitely.
Solution: Designed the Two-Write Lifecycle. The cronHandler() wrapper explicitly writes a running status to the database before execution begins, and then attempts to write success or failed at the end. A separate, lightweight purge-stale reaper job runs periodically to sweep any stranded running jobs and mark them as timeout.
3. Gmail MIME Threading
Problem: Sending an email via the Gmail API is straightforward, but making it appear in the same thread as previous messages requires precise MIME header manipulation (In-Reply-To and References) and sending it as an RFC 2822 base64url encoded string, which standard mailer libraries often abstract away incorrectly.
Solution: Wrote a custom MIME builder service in the Google Integrations slice that manually constructs the multipart boundary payload, allowing precise insertion of the required thread headers alongside user-uploaded PDF resumes.
4. Side-Effect Heavy Account Deletions
Problem: Deleting a user isn't just a database operation. We must actively revoke 3rd-party OAuth grants (Google) and purge external assets (Cloudinary). If we relied on a simple DELETE FROM User and a subsequent API call failed, the user's data would be permanently orphaned on external servers with no way to recover the keys.
Solution: Built the accountDeletion.workflow.ts lock. Instead of deleting the user immediately, Phase 1 locks the account (preventing login) and creates a tombstone record containing all necessary API identifiers. Phase 2 runs the external purges idempotently. Only when all side-effects succeed does Phase 3 trigger the final database cascade.