unleash-proxy-client-swift

unleash-proxy-client-swift 使原生应用程序和其他 swift 平台可以轻松连接到 Unleash 代理。该代理将针对给定的 上下文 评估 Feature Toggle,并返回与提供的上下文相关的 Feature Flag 列表。

unleash-proxy-client-swift 随后会将这些 Toggle 缓存在内存中的一个映射中,并以可配置的时间间隔刷新配置,从而使对 Toggle 配置的查询速度极快。

要求

安装

按照以下步骤安装 unleash-proxy-client-swift

  1. 在您的 Xcode 项目中,转到 File -> Swift Packages -> Add Package Dependency
  2. 提供此存储库的链接
  3. 设置适当的包约束(通常直到下一个主要版本)
  4. 让 Xcode 查找并安装必要的包

完成后,您应该在项目的 File Explorer 中看到 SwiftEventBus 和 UnleashProxyClientSwift 作为依赖项列出。

用法

要开始使用,您需要导入并实例化 Unleash 客户端

iOS >= 13

import SwiftUI
import UnleashProxyClientSwift

// Setup Unleash in the context where it makes most sense

var unleash = UnleashProxyClientSwift.UnleashClient(
    unleashUrl: "https://<unleash-instance>/api/frontend",
    clientKey: "<client-side-api-token>", 
    refreshInterval: 15, 
    appName: "test", 
    context: ["userId": "c3b155b0-5ebe-4a20-8386-e0cab160051e"]
)

unleash.start()

iOS >= 12

import SwiftUI
import UnleashProxyClientSwift

// Setup Unleash in the context where it makes most sense

var unleash = UnleashProxyClientSwift.UnleashClientBase(
    unleashUrl: "https://<unleash-instance>/api/frontend", 
    clientKey: "<client-side-api-token>", 
    refreshInterval: 15, 
    appName: "test", 
    context: ["userId": "c3b155b0-5ebe-4a20-8386-e0cab160051e"]
)

unleash.start()

在上面的示例中,我们导入了 UnleashProxyClientSwift 并实例化了客户端。您需要提供以下参数

运行 unleash.start() 将向代理发出第一个请求并检索 Feature Toggle 配置,并在后台设置轮询间隔。

注意:在等待启动时,配置可能不可用,这意味着如果配置尚未加载,则询问 Feature Toggle 可能会导致 false。 如果您需要确定配置已加载,我们会发出一个事件,您可以在配置加载后订阅该事件。 请参阅“事件”部分了解更多信息。

加载配置后,您可以针对缓存查询给定的 Feature Toggle

if unleash.isEnabled(name: "ios") {
    // do something
} else {
   // do something else
}

您还可以设置 变体,并以类似的方式使用它们

var variant = unleash.getVariant(name: "ios")
if variant.enabled {
    // do something
} else {
   // do something else
}

可用选项

Unleash SDK 采用以下选项

选项 必需 默认值 描述
unleashUrl n/a 要连接的 Unleash Edge/Proxy URL。例如:https://examples.com/proxy
clientKey n/a 要使用的 Unleash Edge/Proxy Secret
appName unleash-swift-client 使用此 SDK 的应用程序的名称。 将用作发送到 Unleash Edge/Proxy 的指标的一部分。 也将是 Unleash Context 的一部分。
environment 默认值 使用此 SDK 的环境的名称。 将用作发送到 Unleash Edge/Proxy 的指标的一部分。 也将是 Unleash Context 的一部分。
refreshInterval 15 SDK 检查更新的 Toggle 配置的频率(以秒为单位)。 如果设置为 0,将禁用检查更新
metricsInterval 30 SDK 将使用情况指标发送回 Unleash Edge/Proxy 的频率(以秒为单位)
disableMetrics false 如果要禁用使用情况指标,请将此选项设置为 true
context [:] 除了 appNameenvironment 之外的初始上下文参数,它们被指定为顶级字段
customHeaders [:] 向 Unleash Edge/Proxy 发出 HTTP 请求时要使用的其他标头。 如果与默认标头发生名称冲突,将使用 customHeaders 值。
customHeadersProvider DefaultCustomHeadersProvider 用于其他标头的自定义标头提供程序。 如果与 customHeaders 发生名称冲突,将使用 customHeadersProvider 值。
bootstrap 空的 Toggle 列表 Unleash Edge/Proxy SDK 可以使用一组初始 Toggle 进行初始化,这些 Toggle 可以从 Toggle 列表中读取,也可以从与前端 API 的响应结构匹配的 jsonFile 中读取。 这些 Toggle 将在初始获取之前立即可用。

引导

您可以向 Unleash 客户端 SDK 提供初始 Toggle 状态。 当您对 Feature Toggle 有已知的初始状态时,这非常有用。 可以通过 Toggle 列表或来自与 前端 API 的响应匹配的文件,将此 Toggle 状态引导到客户端。 例如

从硬编码列表引导

// Note variant and payload can be optional.
let bootstrapList = Bootstrap
    .toggles(
        [
            Toggle(name: "Foo", enabled: true),
            Toggle(
                name: "Bar", 
                enabled: false, 
                variant: Variant(
                    name: "bar",
                    enabled: true,
                    featureEnabled: true,
                    payload: Payload(type: "string", value: "baz")
                )
            )
        ]
    )

从与前端 API 响应匹配的文件引导

{
  "toggles": [
      {
        "name": "no-variant",
        "enabled": true
      },
      {
        "name": "disabled-with-variant-disabled-no-payload",
        "enabled": false,
        "variant": {
            "name": "foo",
            "enabled": false,
            "feature_enabled": false
        }
      },
      {
        "name": "enabled-with-variant-enabled-and-payload",
        "enabled": true,
        "variant": {
            "name": "bar",
            "enabled": true,
            "feature_enabled": true,
            "payload": {
                "type": "string",
                "value": "baz"
            }
        }
      }
  ]
}
guard let filePath = Bundle.main.path(forResource: "FeatureResponseFile", ofType: "json") else {
    // Handle missing file
}

let boostrapFile = Bootsrap.jsonFile(path: filePath)

使用 Toggle 的引导列表

无论是来自硬编码列表还是 json 文件,都可以在初始化时或调用 start 时将引导 Toggle 注入到 Unleash Edge/Proxy 客户端。 例如

import SwiftUI
import UnleashProxyClientSwift

// Setup Unleash in the context where it makes most sense

let unleash = UnleashClient(
    unleashUrl: "https://<unleash-instance>/api/frontend", 
    clientKey: "<client-side-api-token>",
    bootstrap: .toggles([Toggle(name: "Foo", enabled: true)])
)

// Toggles can be accessed now ahead of starting client
let isFooEnabled = unleash.isEnabled(name: "Foo") // true

// Or provide when starting in case of slow/faulty connection
unleash.start(bootstrap: .jsonFile("path/to/json/file"))

// Or using async-await concurrency (>= iOS13)
await unleash.start(bootstrap: .jsonFile("path/to/json/file"))

重要提示

更新上下文

要更新上下文,您可以使用以下方法

var context: [String: String] = [:]
context["userId"] = "c3b155b0-5ebe-4a20-8386-e0cab160051e"
unleash.updateContext(context: context)

这将停止并启动轮询间隔,以便使用新的上下文值续订轮询。

您可以使用任何 预定义的字段。 如果需要支持 自定义属性,请将它们作为第二个参数传递

var context: [String: String] = [:]
context["userId"] = "c3b155b0-5ebe-4a20-8386-e0cab160051e"
var properties: [String: String] = [:]
properties["customKey"] = "customValue";
unleash.updateContext(context: context, properties: properties)

自定义 HTTP 标头

如果您希望客户端在向 Unleash API 发送的所有请求中都发送自定义 HTTP 标头,则可以通过 UnleashClientBase 设置它们来定义它。

自定义和动态自定义标头不适用于敏感标头。

var unleash = UnleashProxyClientSwift.UnleashClientBase(
    unleashUrl: unleashUrl,
    clientKey: clientKey,
    refreshInterval: 15,
    appName: "test",
    context: ["userId": "c3b155b0-5ebe-4a20-8386-e0cab160051e"],
    customHeaders: ["X-Custom-Header": "CustomValue", "X-Another-Header": "AnotherValue"]
)

动态自定义 HTTP 标头

如果您需要客户端生命周期内会更改的自定义 HTTP 标头,则可以通过 UnleashClientBase 定义一个提供程序。

public class MyCustomHeadersProvider: CustomHeadersProvider {
    public init() {}
    public func getCustomHeaders() -> [String: String] {
        let token = "Acquire or refresh token";
        return ["Authorization": token]
    }
}
let myCustomHeadersProvider: CustomHeadersProvider = MyCustomHeadersProvider()

var unleash = UnleashProxyClientSwift.UnleashClientBase(
        unleashUrl: unleashUrl,
        clientKey: clientKey,
        refreshInterval: 15,
        appName: "test",
        context: ["userId": "c3b155b0-5ebe-4a20-8386-e0cab160051e"],
        customHeadersProvider: myCustomHeadersProvider
)

事件

代理客户端会发出您可以订阅的事件。 以下事件可用

以以下方式使用它们

func handleReady() {
    // do this when unleash is ready
}

unleash.subscribe(name: "ready", callback: handleReady)

func handleUpdate() {
    // do this when unleash is updated
}

unleash.subscribe(name: "update", callback: handleUpdate)

或者,这些事件可以作为类型化的枚举 UnleashEvent 被发现和使用,如下所示

unleash.subscribe(.ready, callback: handleUpdate)

在客户端收到第一组 Feature Toggle 并将其缓存在内存中后,将触发 ready 事件。 每个后续事件将是一个 update 事件,如果 Feature Toggle 配置发生更改,则会触发该事件。

发布

注意:要发布该软件包,您需要安装 CocoaPods

使用新的版本号更新 Sources/Version/Version.swift。 它将在 unleash-sdk 标头中使用,作为报告给 Unleash 服务器的版本。

然后,您需要添加与上一步相同的版本号的标签。 发布标签对于 Swift Package Manager 来说就足够了,但确保 CocoaPods 用户也可以使用代码也是一种礼貌的做法。

git tag -a 0.0.4 -m "v0.0.4"

请确保该标签已推送到远程存储库。

以下几个命令假设您已安装 CocoaPods 并且可以在您的 shell 上使用。

首先,使用以下命令验证您与 Cocoapods 的会话

pod trunk register <email> "Your name"

拥有此软件包的电子邮件是 Unleash 团队的通用电子邮件。 Cocoapods 将向此电子邮件发送一个链接,单击该链接以验证您的 shell 会话。

更新软件包的版本号,您可以在 UnleashProxyClientSwift.podspec 中找到它,我们为此项目使用 SemVer。 一旦提交并合并到主分支

Linting podspec 始终是一个好主意

pod spec lint UnleashProxyClientSwift.podspec

一旦成功,您就可以进行实际的发布

pod trunk push UnleashProxyClientSwift.podspec --allow-warnings

测试

为了测试此软件包,您可以运行 swift test 命令。 要测试线程安全,请运行 swift test,并带有

swift test --sanitize=thread

当您有任何数据竞争时,这将在控制台中给出警告。