Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions FlagShip/Source/Cache/FSCacheDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Foundation
/// Called when a visitor set consent to false. Must erase visitor data related to the given visitor
/// Id from the database.
func flushVisitor(visitorId: String)

}

@objc public protocol FSHitCacheDelegate {
Expand Down
6 changes: 3 additions & 3 deletions FlagShip/Source/Cache/FSCacheManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import Foundation
/// - Parameters:
/// - visitoId: id of the visitor
/// - onCompletion: callback ob finishing the job
public func lookupVisitorCache(visitoId: String, onCompletion: @escaping (Error?, FSCacheVisitor?)->Void) {
public func lookupVisitorCache(visitoId: String, onCompletion: @escaping (FlagshipError?, FSCacheVisitor?)->Void) {
/// Create a thread
let fsCacheQueue = DispatchQueue(label: "com.flagshipCache.queue", attributes: .concurrent)
/// Init the semaphore
Expand All @@ -72,10 +72,10 @@ import Foundation
let result = try JSONDecoder().decode(FSCacheVisitor.self, from: dataJson)
onCompletion(nil, result)
} catch {
onCompletion(error, nil)
onCompletion(FlagshipError(message: "Error on decode visitor data from cache", type: .internalError, code: 404), nil)
}
} else {
onCompletion(FlagshipError(type: .internalError, code: 400), nil)
onCompletion(FlagshipError(message: "The visitorId \(visitoId) not found in cache", type: .internalError, code: 400), nil)
}
semaphore.signal()
}
Expand Down
18 changes: 10 additions & 8 deletions FlagShip/Source/Core/FSVisitor+Reconcilliation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ public extension FSVisitor {
/// - Important: After using this method, you should use Flagship.fetchFlags method to update the visitor informations
/// - Requires: Make sure that the experience continuity option is enabled on the flagship platform before using this method
@objc func authenticate(visitorId: String) {
if configManager.flagshipConfig.mode != .DECISION_API {
FlagshipLogManager.Log(level: .ALL, tag: .AUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_AUTHENTICATE)
return
}


// if configManager.flagshipConfig.mode != .DECISION_API {
// FlagshipLogManager.Log(level: .ALL, tag: .AUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_AUTHENTICATE)
// return
// }
self.strategy?.getStrategy().authenticateVisitor(visitorId: visitorId)
self.updateStateAndTriggerCallback(true)
// Troubleshooting xpc
Expand All @@ -27,10 +29,10 @@ public extension FSVisitor {

/// Use authenticate methode to go from Logged in session to logged out session
@objc func unauthenticate() {
if configManager.flagshipConfig.mode != .DECISION_API {
FlagshipLogManager.Log(level: .ALL, tag: .UNAUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_AUTHENTICATE)
return
}
// if configManager.flagshipConfig.mode != .DECISION_API {
// FlagshipLogManager.Log(level: .ALL, tag: .UNAUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_AUTHENTICATE)
// return
// }
self.strategy?.getStrategy().unAuthenticateVisitor()
self.updateStateAndTriggerCallback(false)
// Troubleshooting xpc
Expand Down
5 changes: 5 additions & 0 deletions FlagShip/Source/Core/FSVisitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ import Foundation

// Go to ING state while the fetch is ongoing
self.fetchStatus = .FETCHING

/// Look for the visitor in local storage
self.strategy?.getStrategy().lookupVisitor()

// Synchronize the visitor
self.strategy?.getStrategy().synchronize(onSyncCompleted: { state, reason in

// After the synchronize completion we cache the visitor
Expand Down
2 changes: 1 addition & 1 deletion FlagShip/Source/Core/Flagship.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public class Flagship: NSObject {

if hasConsented {
// Read the cached visitor
newVisitor.strategy?.getStrategy().lookupVisitor()
// newVisitor.strategy?.getStrategy().lookupVisitor() // Déplace la fonction dans le fetch flags
// Read the cacheed hits from data base
newVisitor.strategy?.getStrategy().lookupHits()

Expand Down
2 changes: 1 addition & 1 deletion FlagShip/Source/Logger/FSError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enum ErrorType {
}

// Flagship Error
class FlagshipError: Error {
public class FlagshipError: Error {
var message = ""
var error: ErrorType
let codeError: Int
Expand Down
120 changes: 85 additions & 35 deletions FlagShip/Source/Strategy/FSDefaultStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,39 +177,39 @@ class FSDefaultStrategy: FSDelegateStrategy {
}

func authenticateVisitor(visitorId: String) {
if visitor.configManager.flagshipConfig.mode == .DECISION_API {
/// Update the visitor an anonymous id
if visitor.anonymousId == nil {
visitor.anonymousId = visitor.visitorId
}
// if visitor.configManager.flagshipConfig.mode == .DECISION_API {
/// Update the visitor an anonymous id
if visitor.anonymousId == nil {
visitor.anonymousId = visitor.visitorId
}

// Set the authenticated visitorId
visitor.visitorId = visitorId
// Set the authenticated visitorId
visitor.visitorId = visitorId

// Update fs_users for context
visitor.context.currentContext.updateValue(visitorId, forKey: FS_USERS)
#if os(iOS)
// Update the xpc info for the emotion AI
visitor.emotionCollect?.updateTupleId(visitorId: visitor.visitorId, anonymousId: visitor.anonymousId)
#endif
} else {
FlagshipLogManager.Log(level: .ALL, tag: .AUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_AUTHENTICATE)
}
// Update fs_users for context
visitor.context.currentContext.updateValue(visitorId, forKey: FS_USERS)
#if os(iOS)
// Update the xpc info for the emotion AI
visitor.emotionCollect?.updateTupleId(visitorId: visitor.visitorId, anonymousId: visitor.anonymousId)
#endif
// } else {
// FlagshipLogManager.Log(level: .ALL, tag: .AUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_AUTHENTICATE)
// }
}

func unAuthenticateVisitor() {
if visitor.configManager.flagshipConfig.mode == .DECISION_API {
if let anonymId = visitor.anonymousId {
visitor.visitorId = anonymId
// Update fs_users for context
visitor.context.currentContext.updateValue(anonymId, forKey: FS_USERS)
}
// if visitor.configManager.flagshipConfig.mode == .DECISION_API {
if let anonymId = visitor.anonymousId {
visitor.visitorId = anonymId
// Update fs_users for context
visitor.context.currentContext.updateValue(anonymId, forKey: FS_USERS)
}

visitor.anonymousId = nil
visitor.anonymousId = nil

} else {
FlagshipLogManager.Log(level: .ALL, tag: .AUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_UNAUTHENTICATE)
}
// } else {
// FlagshipLogManager.Log(level: .ALL, tag: .AUTHENTICATE, messageToDisplay: FSLogMessage.IGNORE_UNAUTHENTICATE)
// }
#if os(iOS)
// Update the xpc info for the emotion AI
visitor.emotionCollect?.updateTupleId(visitorId: visitor.visitorId, anonymousId: visitor.anonymousId)
Expand All @@ -226,21 +226,71 @@ class FSDefaultStrategy: FSDelegateStrategy {

/// _ Lookup visitor
func lookupVisitor() {
/// Read the visitor cache from storage
visitor.configManager.flagshipConfig.cacheManager.lookupVisitorCache(visitoId: visitor.visitorId) { error, cachedVisitor in
lookupVisitorWithId(visitor.visitorId)
}

// MARK: - Private Helper Methods

private func lookupVisitorWithId(_ visitorId: String) {
visitor.configManager.flagshipConfig.cacheManager.lookupVisitorCache(visitoId: visitorId) { [weak self] error, cachedVisitor in

if error == nil {
if let aCachedVisitor = cachedVisitor {
self.visitor.mergeCachedVisitor(aCachedVisitor)
/// Get the oldest assignation history before saving and loose the information
self.visitor.assignedVariationHistory.merge(aCachedVisitor.data?.assignationHistory ?? [:]) { _, new in new }
}
guard let strongSelf = self else { return }

if let cachedVisitor = cachedVisitor {
strongSelf.processCachedVisitor(cachedVisitor)
} else if let error = error {
strongSelf.handleLookupError(error, for: visitorId)
}
}
}

private func processCachedVisitor(_ cachedVisitor: FSCacheVisitor?) {
// Ensure thread safety for visitor property modifications
DispatchQueue.main.async { [weak self] in
guard let strongSelf = self else { return }

// Cast to the appropriate cached visitor type
if let aCachedVisitor = cachedVisitor {
strongSelf.visitor.mergeCachedVisitor(aCachedVisitor)

// Safely merge assignation history
let newHistory = aCachedVisitor.data?.assignationHistory ?? [:]
strongSelf.visitor.assignedVariationHistory.merge(newHistory) { _, new in new }
}
}
}

private func handleLookupError(_ error: FlagshipError?, for visitorId: String) {
// Only attempt anonymous lookup for 404 errors and when anonymous ID exists
guard let fsError = error as FlagshipError?,
fsError.codeError == 404,
let anonymousId = visitor.anonymousId,
anonymousId != visitorId else { // Prevent infinite recursion
logLookupError()
return
}

// Lookup anonymous visitor without nesting
lookupAnonymousVisitor(anonymousId)
}

private func lookupAnonymousVisitor(_ anonymousId: String) {
visitor.configManager.flagshipConfig.cacheManager.lookupVisitorCache(visitoId: anonymousId) { [weak self] error, cachedAnonymous in

guard let strongSelf = self else { return }

if let cachedAnonymous = cachedAnonymous {
strongSelf.processCachedVisitor(cachedAnonymous)
} else {
FlagshipLogManager.Log(level: .ALL, tag: .STORAGE, messageToDisplay: .ERROR_ON_READ_FILE)
strongSelf.logLookupError()
}
}
}

private func logLookupError() {
FlagshipLogManager.Log(level: .ALL, tag: .STORAGE, messageToDisplay: .ERROR_ON_READ_FILE)
}

/// _ Flush visitor
func flushVisitor() {
/// Flush the visitor
Expand Down
Loading
Loading