Skip to content

Fix Stale Reads on MySQL in Event Notifications DAO - #142

Open
ThiwankaChanditha wants to merge 2 commits into
wso2:mainfrom
ThiwankaChanditha:fix-stale-reads-mysql
Open

Fix Stale Reads on MySQL in Event Notifications DAO#142
ThiwankaChanditha wants to merge 2 commits into
wso2:mainfrom
ThiwankaChanditha:fix-stale-reads-mysql

Conversation

@ThiwankaChanditha

Copy link
Copy Markdown
Contributor

Problem

In MySQL InnoDB (default REPEATABLE READ isolation level), read queries executed with autoCommit = false establish an MVCC transaction snapshot. Because read operations in event.notifications.dao did not call commitTransaction before returning connections to the Tomcat JDBC pool, connections remained active with uncommitted, frozen snapshots. When requests reused those connections after writes, newly committed records were invisible, causing {"items":[],"total":0} list responses and EN-4040: No subscription exists errors. Reference #107

Scope of Changes

Per ownership boundaries, changes are strictly isolated to org.wso2.dpdp.accelerator.event.notifications.dao:

  1. SubscriptionDAOImpl.java:

    • Added explicit DatabaseUtils.commitTransaction(conn) on success and DatabaseUtils.rollbackTransaction(conn) on catch across:
      • getSubscriptionById(String, String)
      • listSubscriptions(...)
      • getPurposesBySubscriptionId(String, String)
      • countActiveSubscriptionsForTopic(String, String)
      • getPurposesBySubscriptionIds(List<String>)
      • hasPendingOrInFlightDeliveries(String, String)
      • getPendingSubscriptionsForRecovery(Timestamp, int)
    • Inner overloads accepting Connection conn remain untouched.
  2. TopicDAOImpl.java:

    • Added commitTransaction(conn) on success and rollbackTransaction(conn) on catch across:
      • getTopicById(String, String)
      • getTopicByOrgAndName(String, String)
      • listTopics(...)
  3. EventDAOImpl.java:

    • Added commitTransaction(conn) on success and rollbackTransaction(conn) on catch across:
      • getEventById(String, String)
      • getEventPurposes(String)
      • hasActiveEventsForTopic(String)
      • searchEvents(...)
  4. DeliveryDAOImpl.java:

    • Added commitTransaction(conn) on success and rollbackTransaction(conn) on catch across:
      • getWebhookDeliveryById(String, String)
      • loadDispatchContexts(String, int)
      • loadDispatchContextsWithCutoff(String, int, Timestamp)
      • getWebhookDeliveryAudits(String, String)
      • getPollDeliveryById(String, String)
      • getPendingPollDeliveries(...)
      • listSubscriptionDeliveries(...)
      • getSubscriptionDeliveryById(...)
      • listOrgDeliveries(...)
      • getOrgDeliveryById(...)
      • listEventDeliveries(...)
  5. DeliveryAckDAOImpl.java:

    • Added commitTransaction(conn) on success and rollbackTransaction(conn) on catch in getDeliveryAckByDeliveryId(String).

Verification & Testing

1. Automated Unit Tests

  • Command:
    mvn test -pl dpdp-accelerator/components/org.wso2.dpdp.accelerator.event.notifications.dao
  • Results:
    • Tests run: 62, Failures: 0, Errors: 0, Skipped: 2
    • Status: BUILD SUCCESS

2. Manual Testing & Verification

Manual end-to-end tests were performed against a live WSO2 IS instance with MySQL Community Server 8.0:

  1. Pre-fix Reproduction Test:

    • Pre-warmed multiple connection pool leases by issuing 6 parallel GET /subscriptions requests.
    • Inserted a new subscription via POST /subscriptions (15cb9fa6-8a98-4960-89b3-9d0e1bab554a).
    • Immediately issued 8 concurrent GET /subscriptions requests.
    • Observed Bug Behavior: 6 out of 8 requests returned stale count (total: 10) while only 2 returned the fresh count (total: 11), confirming that uncommitted pooled connections were serving frozen snapshots and omitting newly created records. Direct fetch on stale connections yielded EN-4040: No subscription exists with the specified ID for this organization. (404 Not Found).
  2. Post-fix Verification Test:

    • Re-executed the same parallel workflow with the updated DAO bundle deployed.
    • Observed Fixed Behavior: All concurrent GET requests consistently returned the updated total count with 100% consistency, and individual GET /subscriptions/{id} calls consistently returned 200 OK with the active subscription details.
    • Verified that no stale connections or frozen snapshots remain in the Tomcat JDBC connection pool after read requests.

@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: af349f1d-dbf6-4a62-aac2-91db689f41e7


Comment @coderabbitai help to get the list of available commands.

@ThiwankaChanditha ThiwankaChanditha added the Action/trigger-e2e Runs the E2E test suite, including the PR changes label Sep 4, 2026
@github-actions github-actions Bot removed the Action/trigger-e2e Runs the E2E test suite, including the PR changes label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant