# 0070 - Synchronization Strategy for Disappearing Emails (Cache Invalidation & Query Logic) ## Status Accepted ## Context We have identified a recurring synchronization issue where emails disappear from the user's Inbox view despite still existing on the server. This issue affects the reliability of the application and confuses users. ### The Scenario (Observed Behavior) The issue typically manifests in the following sequence, as reported in [Issue #4274](https://github.com/linagora/tmail-flutter/issues/4274): 1. **Day 1:** A user receives "Email A" in their Inbox and reads it. 2. **Day 2:** The user opens the application, but "Email A" is no longer visible in the mail list. 3. **Troubleshooting attempts:** * Switching mailboxes (e.g., to Sent and back to Inbox) does not restore the email. * Clicking the standard UI "Refresh" button has no effect. * **Crucially:** The email *can* be found using the Search function (proving data existence). 4. **Resolution:** The user is forced to **log out and log in**, which magically restores the email to the list. ### Root Cause Analysis The behavior indicates a desynchronization between the local application state (Cache/UI) and the server. The fact that Logout/Login resolves the issue confirms that the local session cache holds stale or corrupted list data that standard soft-refreshes fail to invalidate. ## Decision To resolve this, we are standardizing the **Cache Invalidation** triggers and introducing an **Environment-Controlled Query Strategy** for mailbox switching. ### 1. Standardization of Cache Invalidation Triggers We define specific "Hard Actions" that must strictly trigger a complete cache clearance to ensure data freshness. We move away from "soft updates" for these specific interactions to guarantee the UI reflects the server state. * **F5 (Browser Refresh):** * **Action:** Triggers `clear cache` and reloads application. * **Logout:** * **Action:** Triggers `clear cache` (session wipe) and redirects to login. * **UI Refresh Button:** * **Action:** Triggers `clear cache` explicitly for the current view and re-fetches list from server. * *Rationale:* Previously, this might have only requested a delta update. Now it forces a clean slate fetch for the current list. ### 2. Configurable Mailbox Switching Logic The "Switch Mailbox" action triggers a data query. To prevent the specific conflict or race condition causing the disappearance of emails, we are introducing a feature flag to control the query behavior. We will introduce a new environment variable `FORCE_EMAIL_QUERY`. **Configuration:** In the application's environment file (`env.file`): ```properties # Controls the query strategy when switching mailboxes FORCE_EMAIL_QUERY=false ``` **Logic Flow:** * When a user switches mailboxes, the system checks the `FORCE_EMAIL_QUERY` flag. * **Set to `false` (The Fix):** The application will utilize the optimized query logic (relying on the refined cache/fetch strategy) rather than forcing a heavy query that may be contributing to the state inconsistency observed in the issue. ## Consequences ### Positive 1. **Reliability:** Directly addresses the "disappearing email" bug, ensuring users always see their actual messages. 2. **User Experience:** Eliminates the need for users to perform a disruptive Logout/Login cycle to restore their view. 3. **Maintainability:** By externalizing the logic to an environment variable (`FORCE_EMAIL_QUERY`), we allow DevOps/Developers to toggle query behaviors in different environments without altering source code. 4. **Clarity:** Clearly defines what "Refresh" implies for the system (Clear Cache vs. Delta Update). ### Negative 1. **Performance Overhead:** Forcing a `clear cache` on the UI Refresh button is more resource-intensive than a delta update, potentially leading to slightly longer loading spinners for users with large mailboxes. 2. **Configuration Risk:** Incorrectly setting `FORCE_EMAIL_QUERY` in production environments could revert the fix or alter application behavior unexpectedly. ## Implementation Steps 1. **Event Handling Update:** * Refactor the **Refresh Button**, **F5**, and **Logout** handlers to ensure they explicitly call the `clearCache()` method before fetching new data. 2. **Environment Configuration:** * Add `FORCE_EMAIL_QUERY` to the default `env.file` and set it to `false`. * Update the `AppConfig` or `Environment` class to read this variable. 3. **Mailbox Logic Update:** * Modify the `switchMailbox` function to check the boolean value of `FORCE_EMAIL_QUERY` and apply the corresponding query logic. 4. **Verification:** * Reproduce the scenario (Read email -> Simulate wait/stale state -> Verify visibility). ## References * **GitHub Issue:** [linagora/tmail-flutter#4274](https://github.com/linagora/tmail-flutter/issues/4274)