Skip to content

Commit

Permalink
fix: track bq migration for identify profile events with no attributes
Browse files Browse the repository at this point in the history
Part of: https://linear.app/customerio/issue/MBL-251/track-bq-cdp-migration-causes-crash-in-ios-301-for-identifying-a

If there is an event in the Track BQ for identifying a profile with no profile attributes, the CDP migration could cause a crash. This commit fixes this crash by performing a safe optional unwrap.

Testing consideration:
* Added new unit test reproducing the issue.

commit-id:d1e88742
  • Loading branch information
levibostian committed Apr 16, 2024
1 parent 0023c39 commit 394bb86
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
10 changes: 5 additions & 5 deletions Sources/Migration/DataPipelineMigrationAssistant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,15 @@ public class DataPipelineMigrationAssistant {
guard let trackTaskData: IdentifyProfileQueueTaskData = jsonAdapter.fromJson(taskData) else {
return false
}
if let attributedString = trackTaskData.attributesJsonString, attributedString.contains("null") {
migrationHandler.processIdentifyFromBGQ(identifier: trackTaskData.identifier, timestamp: timestamp, body: nil)
return true
}
guard let profileAttributes: [String: Any] = jsonAdapter.fromJsonString(trackTaskData.attributesJsonString!) else {

// If there are no profile attributes or profile attributes not in a valid format, JSON adapter will return nil and we will perform a migration without the profile attributes.
guard let profileAttributesString: String = trackTaskData.attributesJsonString, let profileAttributes: [String: Any] = jsonAdapter.fromJsonString(profileAttributesString) else {
migrationHandler.processIdentifyFromBGQ(identifier: trackTaskData.identifier, timestamp: timestamp, body: nil)
return true
}

migrationHandler.processIdentifyFromBGQ(identifier: trackTaskData.identifier, timestamp: timestamp, body: profileAttributes)

return true
}

Expand Down
20 changes: 19 additions & 1 deletion Tests/Migration/DataPipelineMigrationAssistantTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class DataPipelineMigrationAssistantTests: UnitTest {

// MARK: getAndProcessTask

func test_givenIdentifyProfileWithoutBody_expectTaskRunAndProcessedDeleted() {
func test_givenIdentifyProfileWithEmptyBody_expectTaskRunAndProcessedDeleted() {
let givenType = QueueTaskType.identifyProfile

let givenCreatedTask = QueueTaskMetadata.random
Expand All @@ -157,6 +157,24 @@ class DataPipelineMigrationAssistantTests: UnitTest {
XCTAssertEqual(backgroundQueueMock.deleteProcessedTaskCallsCount, 1)
}

func test_givenIdentifyProfileWithoutBody_expectTaskRunAndProcessedDeleted() {
let givenType = QueueTaskType.identifyProfile

let givenCreatedTask = QueueTaskMetadata.random

let trackDeliveryMetricData = IdentifyProfileQueueTaskData(identifier: String.random, attributesJsonString: nil)

guard let jsonData = try? JSONEncoder().encode(trackDeliveryMetricData) else {
XCTFail("Failed to create task data")
return
}

backgroundQueueMock.getTaskDetailReturnValue = TaskDetail(data: jsonData, taskType: givenType, timestamp: dateUtilStub.now)

XCTAssertNotNil(migrationAssistant.getAndProcessTask(for: givenCreatedTask, siteId: testSiteId))
XCTAssertEqual(backgroundQueueMock.deleteProcessedTaskCallsCount, 1)
}

func test_givenIdentifyProfileWithBody_expectTaskRunAndProcessedDeleted() {
let givenType = QueueTaskType.identifyProfile
let identifyProfileData = IdentifyProfileQueueTaskData(identifier: String.random, attributesJsonString: "{\"foo\": \"bar\"}")
Expand Down

0 comments on commit 394bb86

Please sign in to comment.