Analytics: Snapshot the site into a value type at the tracking boundary - #25883
Open
jkmassel wants to merge 1 commit into
Open
Conversation
Contributor
|
| App Name | WordPress | |
| Configuration | Release-Alpha | |
| Build Number | 33662 | |
| Version | PR #25883 | |
| Bundle ID | org.wordpress.alpha | |
| Commit | ee53c23 | |
| Installation URL | 39if862uaihlo |
Contributor
|
| App Name | Jetpack | |
| Configuration | Release-Alpha | |
| Build Number | 33662 | |
| Version | PR #25883 | |
| Bundle ID | com.jetpack.alpha | |
| Commit | ee53c23 | |
| Installation URL | 6pl3gu62dvc28 |
jkmassel
force-pushed
the
jkmassel/analytics-module-split
branch
from
August 8, 2026 01:08
09e4a74 to
90e0d43
Compare
Introduce BlogAnalyticsProperties (Sendable) and BlogAnalyticsRepresentable in WordPressShared, conform Blog in WordPressData, and read the snapshot in the two site-attaching track() paths instead of the live managed object. Reading blog.dotComID / blog.isWPForTeams off the object's context queue is a Core Data threading violation: dotComID's getter can write back to the object, and isWPForTeams faults the options relationship. Blog.analyticsProperties takes the snapshot on the object's context queue, so only a Sendable value crosses into analytics. Existing track(..., blog:) call sites compile unchanged because Blog conforms to the protocol. This is the boundary type that unblocks moving analytics into a module that takes no Core Data types.
jkmassel
force-pushed
the
jkmassel/analytics-module-split
branch
from
August 8, 2026 01:31
90e0d43 to
ee53c23
Compare
Contributor
🤖 Build Failure AnalysisThis build has failures. Claude has analyzed them - check the build annotations for details. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Building on #25882, this replaces the raw Core Data
Blogat the analytics boundary with aSendablevalue-type snapshot, so tracking never reads a managed object off its context's queue. It's the load-bearing first step toward extracting analytics into a module that takes no Core Data types.Summary
BlogAnalyticsPropertiesvalue type +BlogAnalyticsRepresentableprotocol inWordPressShared.Blogconforms inWordPressData, snapshotting on its context queue.trackboundaries read from the snapshot, not the liveBlog.Blogconforms, so existingtrack(…, blog:)calls compile unchanged.Root cause
WPAnalytics.track(_:properties:blog:)readblog.dotComIDandblog.isWPForTeamssynchronously, on whatever thread the caller was on. Both are Core Data accesses:Blog.dotComID's getter can write back to the object — it back-fillsblogIDfromjetpack.siteID.isWPForTeamsfaults theoptionsrelationship.Reading either off the object's context queue is a threading violation.
AnalyticsTrackerAutomatticTracks.getSessionInfoalready wraps itsBlogreads incontext.performAndWait— the per-event path was the one place that didn't.Changes
1.
BlogAnalyticsProperties+BlogAnalyticsRepresentable(WordPressShared)A
Sendablestruct carrying the two facts analytics needs —dotComIDandisWPForTeams— and a protocol that vends it. Only this value crosses the model boundary.2.
Blog: BlogAnalyticsRepresentable(WordPressData)analyticsPropertiesreads the two fields insidemanagedObjectContext.performAndWait, so the snapshot is safe to hand to analytics from any thread. Conformance lives with the model — not retroactive.3. Boundary functions read the snapshot (app target)
WPAnalyticsEvent.swift: split into a value-type coretrack(_:properties:blogProperties:)and atrack(_:properties:blog: some BlogAnalyticsRepresentable)convenience that snapshots. The@objc trackEvent(…blog: Blog)andtrackBlockEditorEventforward through it, unchanged.WPAppAnalytics+Extensions.swift:track(_:properties:blog:)readsblog.analyticsPropertiesinstead of touchingdotComID/siteType(for:)directly.Not in this PR
WPAnalyticsEvent,BlogDashboardAnalytics, and the trackers into a standaloneWordPressAnalyticspackage (depends onWordPressShared, notWordPressData) is the follow-up — now unblocked, because the per-event Core Data dependency is severed.AnalyticsTrackerAutomatticTracksstays app-side (it's injected viaregisterTracker), so the module won't needBlog.count(in:)/hasAnyJetpackBlogs.WPAnalytics.domainsProperties(for: blog)(readscanRegisterDomainWithPaidPlan) andWPAppAnalytics.track(_:properties:post:)still take Core Data types. Same treatment, separate PRs.Test plan
BlogAnalyticsPropertiesTestspasses (WP.com / P2 / self-hosted).my_site_dashboard_card_shownstill logsblog_id/site_typefor every card (behavior unchanged from Analytics: Attach the selected site to My Site dashboard card impressions #25882).Related