/
NimbusCreate.swift
89 lines (81 loc) · 3.45 KB
/
NimbusCreate.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
private let remoteSettingsBucket = "main"
private let remoteSettingsCollection = "nimbus-mobile-experiments"
private let logTag = "Nimbus.swift"
private let logger = Logger(tag: logTag)
public let defaultErrorReporter: NimbusErrorReporter = { err in
switch err {
case is LocalizedError:
let description = err.localizedDescription
logger.error("Nimbus error: \(description)")
default:
logger.error("Nimbus error: \(err)")
}
}
public extension Nimbus {
/// Create an instance of `Nimbus`.
///
/// - Parameters:
/// - server: the server that experiments will be downloaded from
/// - appSettings: the name and channel for the app
/// - dbPath: the path on disk for the database
/// - enabled: intended for FeatureFlags. If false, then return a dummy `Nimbus` instance. Defaults to `true`.
/// - errorReporter: a closure capable of reporting errors. Defaults to using a logger.
/// - Returns an implementation of `NimbusApi`.
/// - Throws `NimbusError` if anything goes wrong with the Rust FFI or in the `NimbusClient` constructor.
///
static func create(
_ server: NimbusServerSettings?,
appSettings: NimbusAppSettings,
dbPath: String,
enabled: Bool = true,
errorReporter: @escaping NimbusErrorReporter = defaultErrorReporter
) throws -> NimbusApi {
guard enabled else {
return NimbusDisabled.shared
}
let context = Nimbus.buildExperimentContext(appSettings)
let remoteSettings = server.map { server -> RemoteSettingsConfig in
let url = server.url.absoluteString
return RemoteSettingsConfig(
serverUrl: url,
bucketName: remoteSettingsBucket,
collectionName: remoteSettingsCollection
)
}
let nimbusClient = try NimbusClient(
appCtx: context,
dbpath: dbPath,
remoteSettingsConfig: remoteSettings,
// The "dummy" field here is required for obscure reasons when generating code on desktop,
// so we just automatically set it to a dummy value.
availableRandomizationUnits: AvailableRandomizationUnits(clientId: nil, dummy: 0)
)
return Nimbus(nimbusClient: nimbusClient, errorReporter: errorReporter)
}
static func buildExperimentContext(
_ appSettings: NimbusAppSettings,
bundle: Bundle = Bundle.main,
device: UIDevice = .current
) -> AppContext {
let info = bundle.infoDictionary ?? [:]
return AppContext(
appName: appSettings.appName,
appId: info["CFBundleIdentifier"] as? String ?? "unknown",
channel: appSettings.channel,
appVersion: info["CFBundleShortVersionString"] as? String,
appBuild: info["CFBundleVersion"] as? String,
architecture: Sysctl.machine, // Sysctl is from Glean.
deviceManufacturer: Sysctl.manufacturer,
deviceModel: Sysctl.model,
locale: getLocaleTag(), // from Glean utils
os: device.systemName,
osVersion: device.systemVersion,
androidSdkVersion: nil,
debugTag: "Nimbus.rs"
)
}
}