Transaction Tracker

Bruce Armstrong
CODE AUTHOR
Posts: 65
 2 weeks 5 days ago #709 by Bruce Armstrong
Bruce Armstrong created the code: Transaction Tracker

Transaction Tracker

A transaction object that keeps track of the DataWindows and DataStores using it, so it can re-attach all of them with one call after a reconnect. PowerBuilder 2025, no PFC. Includes a demo and unit tests.

When a PowerBuilder transaction disconnects and connects again, every DataWindow and DataStore that used it has to call SetTransObject again. Transaction Tracker keeps a list of those objects so the transaction can do it for you: n_tracked_trans.of_Reconnect() disconnects, connects and re-attaches every registered object in one call.

What's included (src\tracker.pbl)

  • n_tracked_trans: a transaction that keeps a list of registered objects. It has of_Register, of_Unregister, of_GetReferences, of_Count, of_Prune, of_Reattach, of_Reconnect, and of_Init to read connection settings from an INI file.
  • u_tracked_dw and n_tracked_ds: a DataWindow control and a DataStore. Call of_SetTransObject(name, transaction) instead of SetTransObject; the object registers itself, moves off any previous transaction, and unregisters when it's destroyed.
  • n_trans_ref: one entry in the list (name plus the DataWindow or DataStore).

Registration rules

  • Names must be non-empty and unique within a transaction. A name already used by another object is rejected (NAMEINUSE, -2), as is an empty or null name (INVALIDARGUMENT, -1).
  • Registering the same object again renames it.
  • Objects are unregistered by reference, not by name, so removing one object never removes another's entry.
  • Entries for objects destroyed without unregistering are dropped automatically.

The demo

The tracker application connects SQLCA (an n_tracked_trans) using tracker.ini and opens a window with:

  • a list DataWindow and a detail DataWindow, each with a button to attach it to SQLCA and retrieve;
  • buttons to create and destroy a list DataStore and a detail DataStore;
  • a Reconnect SQLCA and re-attach button, which reconnects the transaction and reports how many objects were re-attached;
  • a listbox showing each registered object's name, type (DataWindow or DataStore) and DataWindow object, so you can watch entries appear when objects attach and disappear when they're destroyed.

Requirements

  • PowerBuilder 2025 (solution format: TransactionTracker.pbsln).
  • For the demo: a database with a project table (project_id, name, project_leader, start_date, end_date). The demo was built against the PEAT demo database on SQL Server. Copy tracker.ini.example to tracker.ini next to the exe and fill in your connection.
  • For the tests: PBUnit 2025, downloaded and extracted into tests\framework. No database is needed; the tests use the Microsoft Text Driver included with Windows. Run pwsh -File tests\run_tests.ps1, which builds the test project with PBAutoBuild and runs 12 tests.

License

MIT License. PBUnit 2025 is a separate project with its own license.

This message has an attachment file.
Please log in or register to see it.

Please Log in or Create an account to join the conversation.

Ramón San Félix Ramón
Posts: 54
 1 week 3 days ago #713 by Ramón San Félix Ramón
Ramón San Félix Ramón replied the code: Transaction Tracker

Thanks a lot for sharing this, Bruce!

  It came at exactly the right time. Our ERP (PowerBuilder 2025, around 1,000 windows) already had half of a
  reconnection mechanism: a timer on the MDI frame that detects a lost connection and connects SQLCA again. But it never
  really worked, because most of our windows call SetTransObject in their open event, which runs only once. After a
  reconnect those DataWindows stayed bound to the dead connection, and the only way out was to close and reopen the
  window. Your tracker was the missing piece.

  Here is how we adapted it:

  - Instead of separate u_tracked_dw / n_tracked_ds classes, we added of_SetTransObject to our existing ancestors (our
    base DataWindow control and our base DataStore). We then replaced SetTransObject with of_SetTransObject across the
    whole application: about 1,600 calls, done with a script, and the compiler pointed out the plain DataWindows and
    DataStores that still had to inherit from those ancestors.
  - Names are generated automatically (parent class + control + a shared counter), so the same window can be open twice
    without a NAMEINUSE conflict.
  - In of_Reattach we also walk the columns with a DropDownDataWindow and call SetTransObject on each DataWindowChild
    that has a SQL source.
  - Along the way we found a bug of our own: our connection service did CREATE transaction on every connect. After a
    reconnect, SQLCA was a different object from the one the DataWindows and our NVOs were holding. Now the transaction
    is created once and reused, and of_Reattach runs right after a successful connect.

  We tested it by killing the ERP's sessions from SQL Server while the windows were open: point of sale, customer
  maintenance and kit assembly all kept working after the reconnect without closing anything. Great work, and thanks
  again for making it MIT!

Please Log in or Create an account to join the conversation.