Skip to content

feat: Migrate MPPersistence + DBMigrationController to Swift - #868

Merged
BrandonStalnaker merged 3 commits into
workstation/swift-migrationfrom
feat/BWS-Swift-Migration-9
Aug 31, 2026
Merged

BrandonStalnaker merged 3 commits into
workstation/swift-migrationfrom
feat/BWS-Swift-Migration-9

Conversation

@BrandonStalnaker

Copy link
Copy Markdown
Collaborator

What
Moves persistence schema logic, internal persistence models, and all persistence File I/O to Swift while retaining thin Objective-C controllers for SQLite operations.

Deletes the Objective-C implementations of:

MPSession
MPMessage
MPUpload
Their Swift replacements retain the existing Objective-C runtime names and selectors through @objc(MPSession), @objc(MPMessage), and @objc(MPUpload).

Persistence logic moved to Swift
MPPersistenceSchemaPRIVATE now owns:

Database versions and names
Paths and directory selection
Size limits
SQL statements and builders
Migration decisions
Legacy sidecar decisions
MPID table metadata
MPDatabaseMigrationLogicPRIVATE owns the SQL used to migrate records between database versions.

SQLite execution and row migration remain in Objective-C so raw SQLite pointers and Objective-C-only dependencies do not cross the module boundary.

Models moved fully to Swift
The Swift models preserve the existing behavior:

MPSession
Thread-safe properties
KVO notifications
Session timing and counter behavior
NSCopying
MPMessage
NSSecureCoding
JSON sanitization and truncation
NSCopying
MPUpload
Upload settings association
Serialization and copying
The Objective-C headers and implementations for these classes are removed.

File I/O and logger injection
Adds MPPersistenceFileSystemPRIVATE, which owns all persistence FileManager operations:

Database directory creation
Documents → Application Support migration
WAL, SHM, and journal sidecar migration
Legacy SessionNumber cleanup
Backup exclusion
Database deletion
Current and legacy path resolution
MPLog is injected from the existing MParticle logger, preserving current log-level and custom-logger behavior.

MPPersistenceController_PRIVATE and MPDatabaseMigrationController now delegate File I/O to this Swift implementation.

Behavior / API
Existing Objective-C runtime class names and selectors are preserved.
Published persistence signatures remain unchanged.
Database initialization and migration ordering is unchanged.
Failed directory migrations preserve the Documents database and continue using it.
Existing Application Support databases take precedence over legacy copies.
Orphan sidecars are removed rather than attached to another database.
No changelog changes; release automation handles them.
Validation
trunk check: clean for changed files.
iOS and tvOS simulator builds: succeeded.
Swift persistence File I/O tests: 9/9 passed.
Objective-C persistence integration tests: 62/62 passed.
Full Swift test suite: passed.
Full Objective-C suite passed

@BrandonStalnaker BrandonStalnaker self-assigned this Aug 26, 2026
@BrandonStalnaker
BrandonStalnaker requested a review from a team as a code owner August 26, 2026 20:34
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes local database location/migration, event message encoding, and session/upload models that underpin all queued analytics and uploads—regressions could lose or mis-route persisted events.

Overview
Completes the Swift migration for core persistence data models by removing the Objective-C MPSession, MPMessage, and MPUpload wrappers. Swift types keep the same ObjC runtime names via @objc(MPSession), @objc(MPMessage), and @objc(MPUpload), with fuller implementations (thread-safe session state, NSSecureCoding on messages, upload settings on uploads).

Adds Swift-owned persistence metadata and file I/O: MPPersistenceSchemaPRIVATE (paths, schema SQL, size limits, migration decisions), MPDatabaseMigrationLogicPRIVATE (version-migration SQL), and MPPersistenceFileSystemPRIVATE (directory creation, Documents→Application Support migration, sidecars, backup exclusion). MPPersistenceController and MPDatabaseMigrationController still run SQLite but delegate path/schema/file work to Swift with injected MPLog.

Tests and mocks now import mParticle_Apple_SDK_Swift and use MPSessionPRIVATE where needed; MPUserDefaults.storedMpId() backs default session initialization.

Reviewed by Cursor Bugbot for commit 3d9b5e4. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

🐦 Swift Migration Progress

Production implementation code at 3d9b5e44d422 compared with a16b1e84e8df.

Area Goal Progress Base This PR Swift SLOC Objective-C remaining Change
Core SDK Short term — in scope ████▏░░░░░ 35.43% 41.04% 5,881 8,450 🚀 +5.61 pp
Core SDK Long term — all Objective-C ██▉░░░░░░░ 25.14% 29.13% 5,881 14,305 🚀 +3.99 pp
SDK kit infrastructure Short term — in scope ░░░░░░░░░░ 0.00% 0.00% 0 3,340 ➖ 0.00 pp
SDK kit infrastructure Long term — all Objective-C ░░░░░░░░░░ 0.00% 0.00% 0 3,725 ➖ 0.00 pp
Standalone kits Short term — in scope ▏░░░░░░░░░ 1.06% 1.06% 152 14,231 ➖ 0.00 pp
Standalone kits Long term — all Objective-C ▏░░░░░░░░░ 1.06% 1.06% 152 14,231 ➖ 0.00 pp

Objective-C retained by design: Core SDK 5,855 (-5) · SDK kit infrastructure 385 · Standalone kits 0.

This PR's code movement

Area Swift lines added Objective-C lines removed
Core SDK 1,024 1,012
SDK kit infrastructure 0 0
Standalone kits 0 0
How this is measured
  • Current composition uses production source lines of code (SLOC) from cloc; comments and blank lines are excluded.
  • Short term — in scope excludes the Objective-C the migration will not delete, so 100% is the end of this project: every in-scope implementation gone.
  • Long term — all Objective-C keeps the full denominator. Reaching 100% there means the public API itself becomes Swift, which is a breaking change reserved for a future major release.
  • The gap between the two rows is the retained public/kit contract, runtime-identity, and boundary-glue surface listed in Tools/swift-migration-retained-objc.txt.
  • Retained wrappers keep their Objective-C interface but still shed logic to Swift. That thinning moves the long-term row and the retained figure, not the short-term row.
  • Both revisions are measured with the manifest from the head revision, so a manifest edit does not by itself move the reported change. A retained file this pull request renamed or deleted still counts as retained at the base.
  • Pull request movement uses physical additions/deletions from git diff base...head --numstat; it counts retained files too and is intentionally separate from SLOC totals.
  • Core excludes SDK kit infrastructure and vendored libraries. Standalone kits include only files below Kits/**/Sources.
  • Tests, examples, headers, build outputs, vendored libraries, and the MParticle/Sources Swift overlay are excluded.
  • Objective-C++ (.mm) is included in the Objective-C figures and removed counts.

Generated with cloc 2.10. This report is informational and does not gate migration direction.

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

📦 SDK Size Impact Report

Measures how much the SDK adds to an app's size (with-SDK minus without-SDK).

Metric Target Branch This PR Change
App Bundle Impact 2.12 MB 2.14 MB +24 KB
Executable Impact 848 bytes 848 bytes +N/A
XCFramework Size 6.72 MB 6.68 MB -44 KB

➡️ SDK size impact change is minimal.

Raw measurements

Target branch (workstation/swift-migration):

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":2256,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":2172,"sdk_executable_impact_bytes":848,"xcframework_size_kb":6880}

This PR:

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":2280,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":2196,"sdk_executable_impact_bytes":848,"xcframework_size_kb":6836}

Fully convert MPSession, MPUpload, and MPMessage
@BrandonStalnaker
BrandonStalnaker force-pushed the feat/BWS-Swift-Migration-9 branch from c464e89 to 2f60018 Compare August 27, 2026 14:01

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2f60018. Configure here.

Comment thread mParticle-Apple-SDK/Persistence/MPDatabaseMigrationController.m Outdated
Chained UTF8String on temporary Swift NSStrings can dangle before sqlite3_prepare_v2, which can skip or crash queued-event migration. Prepare from a retained NSString so the SQL buffer stays valid.

Empty MPSession init hardcoded userId 0 after the ObjC facade was removed. Read the stored MPID from user defaults, matching the previous persistence lookup.
@BrandonStalnaker
BrandonStalnaker merged commit 206fa3a into workstation/swift-migration Aug 31, 2026
81 checks passed
@BrandonStalnaker
BrandonStalnaker deleted the feat/BWS-Swift-Migration-9 branch August 31, 2026 18:01
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.

3 participants