Skip to content

Commit 2004900

Browse files
committed
Add CLS support
1 parent 3f1fddf commit 2004900

File tree

6 files changed

+191
-6
lines changed

6 files changed

+191
-6
lines changed

Package.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ let package = Package(
1818
.library(name: "TencentSCFTesting", targets: ["TencentSCFTesting"]),
1919
],
2020
dependencies: [
21-
.package(url: "https://github.com/apple/swift-nio.git", .upToNextMajor(from: "2.17.0")),
22-
.package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.0.0")),
23-
.package(url: "https://github.com/swift-server/swift-backtrace.git", .upToNextMajor(from: "1.1.0")),
24-
.package(url: "https://github.com/stevapple/tencent-cloud-core.git", .upToNextMajor(from: "0.2.0"))
21+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.17.0"),
22+
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
23+
.package(url: "https://github.com/swift-server/swift-backtrace.git", from: "1.1.0"),
24+
.package(url: "https://github.com/stevapple/tencent-cloud-core.git", .upToNextMinor(from: "0.2.0")),
25+
.package(name: "Gzip", url: "https://github.com/1024jp/GzipSwift.git", from: "5.1.0")
2526
],
2627
targets: [
2728
.target(name: "TencentSCFRuntime", dependencies: [
@@ -44,7 +45,9 @@ let package = Package(
4445
.product(name: "NIOTestUtils", package: "swift-nio"),
4546
.product(name: "NIOFoundationCompat", package: "swift-nio"),
4647
]),
47-
.target(name: "TencentSCFEvents", dependencies: []),
48+
.target(name: "TencentSCFEvents", dependencies: [
49+
.byName(name: "Gzip")
50+
]),
4851
.testTarget(name: "TencentSCFEventsTests", dependencies: ["TencentSCFEvents"]),
4952
// testing helper
5053
.target(name: "TencentSCFTesting", dependencies: [

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ Serverless Cloud Functions can be invoked directly from the SCF console, SCF API
400400
* [Timer Events](https://intl.cloud.tencent.com/document/product/583/9708)
401401
* [CMQ Topic Messages](https://intl.cloud.tencent.com/document/product/583/11517)
402402
* [CKafka Messages](https://intl.cloud.tencent.com/document/product/583/17530)
403+
* [CLS Logs](https://intl.cloud.tencent.com/document/product/583/38845)
403404

404405
**Note**: Each one of the integration points mentioned above includes a set of `Decodable` structs that transform Tencent Cloud's data model for these APIs. APIGateway response is wrapped into an `Encodable` struct with three different initializers to help you build any valid response.
405406

Sources/TencentSCFEvents/APIResponse.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the SwiftTencentSCFRuntime open source project
44
//
5-
// Copyright (c) 2020 stevapple and the SwiftTencentSCFRuntime project authors
5+
// Copyright (c) 2020-2021 stevapple and the SwiftTencentSCFRuntime project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===------------------------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftTencentSCFRuntime open source project
4+
//
5+
// Copyright (c) 2021 stevapple and the SwiftTencentSCFRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftTencentSCFRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===------------------------------------------------------------------------------------===//
14+
15+
import Gzip
16+
import struct Foundation.Data
17+
import struct Foundation.Date
18+
19+
// https://intl.cloud.tencent.com/document/product/583/38845
20+
21+
import class Foundation.JSONDecoder
22+
23+
public enum CLS {
24+
public struct Logs: Decodable {
25+
public let topicId: String
26+
public let topicName: String
27+
public let records: [CLS.Record]
28+
29+
public init(from decoder: Decoder) throws {
30+
let rawContainer = try decoder.singleValueContainer()
31+
let data = try rawContainer.decode(CLS.Raw.self).data.gunzipped()
32+
33+
let _self = try CLS.jsonDecoder.decode(CLS._Logs.self, from: data)
34+
self.topicId = _self.topicId
35+
self.topicName = _self.topicName
36+
self.records = _self.records
37+
}
38+
}
39+
40+
public struct Record: Decodable {
41+
public let timestamp: UInt
42+
public let content: String
43+
44+
public var date: Date {
45+
Date(timeIntervalSince1970: Double(timestamp) / 1000)
46+
}
47+
48+
enum CodingKeys: String, CodingKey {
49+
case timestamp
50+
case content
51+
}
52+
53+
public init(from decoder: Decoder) throws {
54+
let container = try decoder.container(keyedBy: CodingKeys.self)
55+
let timestring = try container.decode(String.self, forKey: .timestamp)
56+
guard let timestamp = UInt(timestring) else {
57+
throw DecodingError.dataCorruptedError(forKey: .timestamp, in: container, debugDescription: "Expected timestamp to be unsigned numbers")
58+
}
59+
self.timestamp = timestamp
60+
self.content = try container.decode(String.self, forKey: .content)
61+
}
62+
}
63+
64+
internal static let jsonDecoder = JSONDecoder()
65+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===------------------------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftTencentSCFRuntime open source project
4+
//
5+
// Copyright (c) 2021 stevapple and the SwiftTencentSCFRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftTencentSCFRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===------------------------------------------------------------------------------------===//
14+
15+
import struct Foundation.Data
16+
17+
// https://intl.cloud.tencent.com/document/product/583/38845
18+
19+
extension CLS{
20+
struct _Logs: Decodable {
21+
let topicId: String
22+
let topicName: String
23+
let records: [CLS.Record]
24+
25+
enum CodingKeys: String, CodingKey {
26+
case topicId = "topic_id"
27+
case topicName = "topic_name"
28+
case records
29+
}
30+
}
31+
32+
struct Raw: Decodable {
33+
let data: Data
34+
35+
enum WrappingCodingKeys: String, CodingKey {
36+
case logs = "clslogs"
37+
}
38+
enum CodingKeys: String, CodingKey {
39+
case data
40+
}
41+
42+
public init(from decoder: Decoder) throws {
43+
let wrapperContainer = try decoder.container(keyedBy: WrappingCodingKeys.self)
44+
let container = try wrapperContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .logs)
45+
let rawString = try container.decode(String.self, forKey: .data)
46+
guard let data = Data(base64Encoded: rawString) else {
47+
throw DecodingError.dataCorruptedError(forKey: .data, in: container, debugDescription: "Base64 decoding error")
48+
}
49+
self.data = data
50+
}
51+
}
52+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===------------------------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftTencentSCFRuntime open source project
4+
//
5+
// Copyright (c) 2021 stevapple and the SwiftTencentSCFRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftTencentSCFRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===------------------------------------------------------------------------------------===//
14+
15+
import Gzip
16+
@testable import TencentSCFEvents
17+
import XCTest
18+
19+
class CLSLogTests: XCTestCase {
20+
static let realBody = """
21+
{
22+
"topic_id": "xxxx-xx-xx-xx-yyyyyyyy",
23+
"topic_name": "testname",
24+
"records": [{
25+
"timestamp": "1605578090000020",
26+
"content": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
27+
}, {
28+
"timestamp": "1605578090000040",
29+
"content": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
30+
}]
31+
}
32+
"""
33+
34+
static var eventBody: String {
35+
let data = try! realBody.data(using: .utf8)!.gzipped().base64EncodedString()
36+
return """
37+
{
38+
"clslogs": {
39+
"data": "\(data)"
40+
}
41+
}
42+
"""
43+
}
44+
45+
func testSimpleEventFromJSON() {
46+
let data = Self.eventBody.data(using: .utf8)!
47+
var event: CLS.Logs?
48+
XCTAssertNoThrow(event = try JSONDecoder().decode(CLS.Logs.self, from: data))
49+
50+
XCTAssertEqual(event?.topicId, "xxxx-xx-xx-xx-yyyyyyyy")
51+
XCTAssertEqual(event?.topicName, "testname")
52+
guard let record1 = event?.records.first,
53+
let record2 = event?.records.last else {
54+
XCTFail("Expected to have 2 records")
55+
return
56+
}
57+
58+
XCTAssertEqual(record1.content, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
59+
XCTAssertEqual(record2.content, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy")
60+
XCTAssertEqual(record1.timestamp, 1605578090000020)
61+
XCTAssertEqual(record2.timestamp, 1605578090000040)
62+
XCTAssertEqual(record2.date.timeIntervalSince(record1.date), 0.02, accuracy: 0.0001)
63+
}
64+
}

0 commit comments

Comments
 (0)