Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 1 addition & 29 deletions Examples/destination_plugins/AdjustDestination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ public class AdjustDestination: NSObject, DestinationPlugin, RemoteNotifications

internal var settings: AdjustSettings? = nil

@Atomic var started = false

required public init(name: String) {
self.name = name
}
Expand Down Expand Up @@ -87,13 +85,9 @@ public class AdjustDestination: NSObject, DestinationPlugin, RemoteNotifications
}

Adjust.appDidLaunch(adjustConfig)

started = true
}

public func identify(event: IdentifyEvent) -> IdentifyEvent? {
guard started == true else { return event }

if let userId = event.userId, userId.count > 0 {
Adjust.addSessionPartnerParameter("user_id", value: userId)
}
Expand All @@ -106,8 +100,6 @@ public class AdjustDestination: NSObject, DestinationPlugin, RemoteNotifications
}

public func track(event: TrackEvent) -> TrackEvent? {
guard started == true else { return event }

if let anonId = event.anonymousId, anonId.count > 0 {
Adjust.addSessionPartnerParameter("anonymous_id", value: anonId)
}
Expand Down Expand Up @@ -139,19 +131,11 @@ public class AdjustDestination: NSObject, DestinationPlugin, RemoteNotifications
return event
}

public func screen(event: ScreenEvent) -> ScreenEvent? {
guard started == true else { return event }

return event
}

public func reset() {
guard started == true else { return }
Adjust.resetSessionPartnerParameters()
}

public func registeredForRemoteNotifications(deviceToken: Data) {
guard started == true else { return }
Adjust.setDeviceToken(deviceToken)
}
}
Expand All @@ -177,6 +161,7 @@ extension AdjustDestination: AdjustDelegate {
analytics?.track(name: "Install Attributed", properties: properties)
}
}

// MARK: - Support methods

extension AdjustDestination {
Expand Down Expand Up @@ -204,16 +189,3 @@ extension AdjustDestination {
return result
}
}

// we are missing support for:
/*
reset()
flush()
receivedRemoteNotification
failedToRegisterForRemoteNotification
registerForRemoteNotifications(deviceToken:)
handleActionWithIdentifier
continueUserActivity
openURL:options:
*/

2 changes: 0 additions & 2 deletions Examples/destination_plugins/AmplitudeSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ extension AmplitudeSession {

@objc
func handleTimerFire(_ timer: Timer) {
print("Timer Fired")
print("Session: \(sessionID ?? -1)")
stopTimer()
startTimer()
}
Expand Down
8 changes: 0 additions & 8 deletions Examples/destination_plugins/FlurryDestination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class FlurryDestination: DestinationPlugin {
let name: String
var analytics: Analytics? = nil

var started = false
var screenTracksEvents = false

required init(name: String) {
Expand All @@ -70,12 +69,9 @@ class FlurryDestination: DestinationPlugin {
}

Flurry.startSession(flurryApiKey, with: builder)
started = true
}

func identify(event: IdentifyEvent) -> IdentifyEvent? {
guard started == true else { return event }

Flurry.setUserID(event.userId)

if let traits = event.traits?.dictionaryValue {
Expand All @@ -92,16 +88,12 @@ class FlurryDestination: DestinationPlugin {
}

func track(event: TrackEvent) -> TrackEvent? {
guard started == true else { return event }

let props = truncate(properties: event.properties?.dictionaryValue)
Flurry.logEvent(event.event, withParameters: props)
return event
}

func screen(event: ScreenEvent) -> ScreenEvent? {
guard started == true else { return event }

if screenTracksEvents {
let props = truncate(properties: event.properties?.dictionaryValue)
Flurry.logEvent("Viewed \(event.name ?? "") Screen", withParameters: props)
Expand Down
3 changes: 1 addition & 2 deletions Examples/destination_plugins/MixpanelDestination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ class MixpanelDestination: DestinationPlugin {
}
}

func identify(event: IdentifyEvent) -> IdentifyEvent? {

func identify(event: IdentifyEvent) -> IdentifyEvent? {
// Ensure that the userID is set and valid
if let eventUserID = event.userId, !eventUserID.isEmpty {
mixpanel?.identify(distinctId: eventUserID)
Expand Down
1 change: 1 addition & 0 deletions Examples/other_plugins/ConsentTracking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class ConsentTracking: Plugin {
for instance in Self.instances {
instance.replayEvents()
}
clearQueuedEvents()
}

func replayEvents() {
Expand Down
4 changes: 4 additions & 0 deletions Segment.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
46022764261E64A800A9E913 /* iOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46022763261E64A800A9E913 /* iOSLifecycleEvents.swift */; };
4602276C261E7BF900A9E913 /* iOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4602276B261E7BF900A9E913 /* iOSDelegation.swift */; };
46022771261F7A4800A9E913 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46022770261F7A4800A9E913 /* Atomic.swift */; };
46031D65266E7C10009BA540 /* StartupQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46031D64266E7C10009BA540 /* StartupQueue.swift */; };
462107F22603DA4D00EBC4A8 /* Sovran in Frameworks */ = {isa = PBXBuildFile; productRef = 462107F12603DA4D00EBC4A8 /* Sovran */; };
4621080C2605332D00EBC4A8 /* KeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4621080B2605332D00EBC4A8 /* KeyPath.swift */; };
46210811260538BE00EBC4A8 /* KeyPath_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46210810260538BE00EBC4A8 /* KeyPath_Tests.swift */; };
Expand Down Expand Up @@ -103,6 +104,7 @@
46022763261E64A800A9E913 /* iOSLifecycleEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSLifecycleEvents.swift; sourceTree = "<group>"; };
4602276B261E7BF900A9E913 /* iOSDelegation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSDelegation.swift; sourceTree = "<group>"; };
46022770261F7A4800A9E913 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
46031D64266E7C10009BA540 /* StartupQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StartupQueue.swift; sourceTree = "<group>"; };
4621080B2605332D00EBC4A8 /* KeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPath.swift; sourceTree = "<group>"; };
46210810260538BE00EBC4A8 /* KeyPath_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPath_Tests.swift; sourceTree = "<group>"; };
46210835260BBEE400EBC4A8 /* DeviceToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceToken.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -211,6 +213,7 @@
46A018C125E5857D00F9CCD8 /* Context.swift */,
9692726725A583A6009B5298 /* SegmentDestination.swift */,
46210835260BBEE400EBC4A8 /* DeviceToken.swift */,
46031D64266E7C10009BA540 /* StartupQueue.swift */,
);
path = Plugins;
sourceTree = "<group>";
Expand Down Expand Up @@ -469,6 +472,7 @@
46A018C225E5857D00F9CCD8 /* Context.swift in Sources */,
96208650257AA83E00314F8D /* iOSLifecycleMonitor.swift in Sources */,
96C33AAC25892D6D00F3D538 /* Metrics.swift in Sources */,
46031D65266E7C10009BA540 /* StartupQueue.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
6 changes: 2 additions & 4 deletions Sources/Segment/Analytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ public class Analytics {
internal var configuration: Configuration
internal var store: Store
internal var storage: Storage

private var built = false


/// Enabled/disables debug logging to trace your data going through the SDK.
public var debugLogsEnabled = false

Expand All @@ -33,7 +31,7 @@ public class Analytics {
store.provide(state: System.defaultState(configuration: configuration, from: storage))
store.provide(state: UserInfo.defaultState(from: storage))

// Get everything hot and sweaty here
// Get everything running
platformStartup()
}

Expand Down
18 changes: 18 additions & 0 deletions Sources/Segment/Plugins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,29 @@ extension Analytics {
*/
@discardableResult
public func add(plugin: Plugin) -> String {
// we need to know if the system is already started.
var wasStarted = false
if let system: System = store.currentState(), system.started {
wasStarted = system.started
// if it was, we need to stop it temporarily.
store.dispatch(action: System.SetStartedAction(started: false))
// adding the plugin to the timeline below will eventually call
// update(settings:) at which point, we can start it up again.
}

plugin.configure(analytics: self)
timeline.add(plugin: plugin)
if plugin is DestinationPlugin && !(plugin is SegmentDestination) {
// need to maintain the list of integrations to inject into payload
store.dispatch(action: System.AddIntegrationAction(pluginName: plugin.name))
}

// if the timeline had started before, set it back to started since
// update(settings:) will have been called by now.
if wasStarted {
store.dispatch(action: System.SetStartedAction(started: true))
}

return plugin.name
}

Expand Down
56 changes: 56 additions & 0 deletions Sources/Segment/Plugins/StartupQueue.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// StartupQueue.swift
// Segment
//
// Created by Brandon Sneed on 6/4/21.
//

import Foundation
import Sovran

class StartupQueue: Plugin, Subscriber {
static var specificName = "Segment_StartupQueue"

@Atomic var started: Bool = false

let type: PluginType = .before
let name: String = specificName
var analytics: Analytics? = nil {
didSet {
analytics?.store.subscribe(self, handler: systemUpdate)
}
}

var queuedEvents = [RawEvent]()

required init(name: String) {
// ignore name; hardcoded above.
}

func execute<T: RawEvent>(event: T?) -> T? {
if let e = event, started == false {
// timeline hasn't started, so queue it up.
queuedEvents.append(e)
return nil
}
// the timeline has started, so let the event pass.
return event
}
}

extension StartupQueue {
internal func systemUpdate(state: System) {
started = state.started
if started {
replayEvents()
}
}

internal func replayEvents() {
// replay the queued events to the instance of Analytics we're working with.
for event in queuedEvents {
analytics?.process(event: event)
}
queuedEvents.removeAll()
}
}
1 change: 1 addition & 0 deletions Sources/Segment/Startup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ extension Analytics: Subscriber {
if let settings = state.settings {
self.update(settings: settings)
}
self.store.dispatch(action: System.SetStartedAction(started: true))
}

// plugins will receive any settings we currently have as they are added.
Expand Down
24 changes: 20 additions & 4 deletions Sources/Segment/State.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ struct System: State {
let configuration: Configuration
let integrations: JSON?
let settings: Settings?
let started: Bool

struct UpdateSettingsAction: Action {
let settings: Settings

func reduce(state: System) -> System {
let result = System(configuration: state.configuration,
integrations: state.integrations,
settings: settings)
settings: settings,
started: state.started)
return result
}
}
Expand All @@ -39,7 +41,8 @@ struct System: State {
if let jsonIntegrations = try? JSON(integrations) {
let result = System(configuration: state.configuration,
integrations: jsonIntegrations,
settings: state.settings)
settings: state.settings,
started: state.started)
return result
}
}
Expand All @@ -56,13 +59,26 @@ struct System: State {
if let jsonIntegrations = try? JSON(integrations) {
let result = System(configuration: state.configuration,
integrations: jsonIntegrations,
settings: state.settings)
settings: state.settings,
started: state.started)
return result
}
}
return state
}
}

struct SetStartedAction: Action {
let started: Bool

func reduce(state: System) -> System {
let result = System(configuration: state.configuration,
integrations: state.integrations,
settings: state.settings,
started: started)
return result
}
}
}


Expand Down Expand Up @@ -126,7 +142,7 @@ extension System {
}
}
let integrationDictionary = try! JSON([String: Any]())
return System(configuration: configuration, integrations: integrationDictionary, settings: settings)
return System(configuration: configuration, integrations: integrationDictionary, settings: settings, started: false)
}
}

Expand Down