File size: 3,101 Bytes
788eab4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# IMATS ERP Integration Architecture

This document specifies the integration architecture between the Collegiate Placement Engine and IMATS (Institutional Management & Academic Tracking System) or enterprise campus ERPs.

---

## 1. Architectural Pattern: Hexagonal Ports and Adapters

The placement engine isolates external enterprise systems behind an explicit domain port:
- **Port Interface**: [`backend.app.integrations.imats.interface.IIMATSClient`](backend/app/integrations/imats/interface.py)
- **Production/Sandbox Adapter**: [`backend.app.integrations.imats.client.SandboxIMATSClient`](backend/app/integrations/imats/client.py)
- **Offline Outbox Engine**: [`backend.app.integrations.imats.outbox.IMATSOutboxManager`](backend/app/integrations/imats/outbox.py)

---

## 2. Key Reliability Guarantees

### A. Idempotency Keys
Every outbound sync operation (`push_shortlist`, `push_schedule`) requires an unguessable `idempotency_key`. The server and client deduplicate duplicate submissions, guaranteeing that network reconnects or retry storms never duplicate records or schedule slots.

### B. Exponential Backoff with Jitter
When transient network interruptions occur across the college intranet, the client performs exponential backoff:
$$\text{delay} = \text{initial\_backoff} \times 2^{\text{attempt}}$$

By default, the client makes 3 retry attempts before delegating to the offline outbox.



### C. Offline Outbox Pattern

When the campus LAN is severed or the remote IMATS server is in a maintenance window:

1. Shortlists and schedules are persisted to the local outbox marked as `PENDING`.

2. When connectivity is re-established, the officer or background automation calls `/api/imats/sync` to flush pending items reliably.



---



## 3. How to Swap in the Live Production Endpoint



To connect to a live institutional IMATS ERP instance:



1. Create a concrete class `LiveIMATSClient` implementing `IIMATSClient`:

   ```python

   import httpx

   from backend.app.integrations.imats.interface import IIMATSClient



   class LiveIMATSClient(IIMATSClient):

       def __init__(self, base_url: str, api_token: str):

           self.base_url = base_url

           self.headers = {

               "Authorization": f"Bearer {api_token}",
               "Content-Type": "application/json",

           }


       def push_shortlist(self, drive_id: str, student_ids: list[str], idempotency_key: str):

           resp = httpx.post(

               f"{self.base_url}/api/v1/drives/{drive_id}/shortlist",

               json={"student_ids": student_ids},

               headers={**self.headers, "Idempotency-Key": idempotency_key},

               timeout=15.0,

           )

           resp.raise_for_status()

           return resp.json()

   ```


2. Register the live adapter in `backend/app/api/main.py` using standard dependency injection:
   ```python

   imats_client = LiveIMATSClient(

       base_url=os.getenv("IMATS_BASE_URL", "https://imats.college.edu/api"),

       api_token=os.getenv("IMATS_API_TOKEN", "secret"),

   )

   ```