Skip to content

Commit 5c200b5

Browse files
committed
Use aws lambda v2
1 parent 7aabafe commit 5c200b5

File tree

12 files changed

+272
-156
lines changed

12 files changed

+272
-156
lines changed

Lambdas/AutoFaqs/AutoFaqsHandler.swift

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,40 @@ import Foundation
1414
#endif
1515

1616
@main
17-
struct AutoFaqsHandler: LambdaHandler {
18-
typealias Event = APIGatewayV2Request
19-
typealias Output = APIGatewayV2Response
17+
@dynamicMemberLookup
18+
struct AutoFaqsHandler {
19+
struct SharedContext {
20+
let awsClient: AWSClient
21+
}
22+
23+
subscript<T>(dynamicMember keyPath: KeyPath<SharedContext, T>) -> T {
24+
get {
25+
sharedContext[keyPath: keyPath]
26+
}
27+
}
2028

21-
let awsClient: AWSClient
29+
let sharedContext: SharedContext
2230
let autoFaqsRepo: S3AutoFaqsRepository
2331

24-
init(context: LambdaInitializationContext) async {
32+
static func main() async throws {
2533
let httpClient = HTTPClient(
26-
eventLoopGroupProvider: .shared(context.eventLoop),
34+
eventLoopGroupProvider: .shared(Lambda.defaultEventLoop),
2735
configuration: .forPenny
2836
)
29-
self.awsClient = AWSClient(httpClient: httpClient)
30-
self.autoFaqsRepo = S3AutoFaqsRepository(awsClient: self.awsClient, logger: context.logger)
37+
let awsClient = AWSClient(httpClient: httpClient)
38+
let sharedContext = SharedContext(awsClient: awsClient)
39+
try await LambdaRuntime { (event: APIGatewayV2Request, context: LambdaContext) in
40+
let handler = AutoFaqsHandler(context: context, sharedContext: sharedContext)
41+
return await handler.handle(event)
42+
}.run()
43+
}
44+
45+
init(context: LambdaContext, sharedContext: SharedContext) {
46+
self.sharedContext = sharedContext
47+
self.autoFaqsRepo = S3AutoFaqsRepository(awsClient: sharedContext.awsClient, logger: context.logger)
3148
}
3249

33-
func handle(
34-
_ event: APIGatewayV2Request,
35-
context: LambdaContext
36-
) async -> APIGatewayV2Response {
50+
func handle(_ event: APIGatewayV2Request) async -> APIGatewayV2Response {
3751
let request: AutoFaqsRequest
3852
do {
3953
request = try event.decode()

Lambdas/AutoPings/AutoPingsHandler.swift

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,40 @@ import Foundation
1414
#endif
1515

1616
@main
17-
struct AutoPingsHandler: LambdaHandler {
18-
typealias Event = APIGatewayV2Request
19-
typealias Output = APIGatewayV2Response
17+
@dynamicMemberLookup
18+
struct AutoPingsHandler {
19+
struct SharedContext {
20+
let awsClient: AWSClient
21+
}
22+
23+
subscript<T>(dynamicMember keyPath: KeyPath<SharedContext, T>) -> T {
24+
get {
25+
sharedContext[keyPath: keyPath]
26+
}
27+
}
2028

21-
let awsClient: AWSClient
29+
let sharedContext: SharedContext
2230
let pingsRepo: S3AutoPingsRepository
2331

24-
init(context: LambdaInitializationContext) async {
32+
static func main() async throws {
2533
let httpClient = HTTPClient(
26-
eventLoopGroupProvider: .shared(context.eventLoop),
34+
eventLoopGroupProvider: .shared(Lambda.defaultEventLoop),
2735
configuration: .forPenny
2836
)
29-
self.awsClient = AWSClient(httpClient: httpClient)
30-
self.pingsRepo = S3AutoPingsRepository(awsClient: self.awsClient, logger: context.logger)
37+
let awsClient = AWSClient(httpClient: httpClient)
38+
let sharedContext = SharedContext(awsClient: awsClient)
39+
try await LambdaRuntime { (event: APIGatewayV2Request, context: LambdaContext) in
40+
let handler = AutoPingsHandler(context: context, sharedContext: sharedContext)
41+
return await handler.handle(event)
42+
}.run()
43+
}
44+
45+
init(context: LambdaContext, sharedContext: SharedContext) {
46+
self.sharedContext = sharedContext
47+
self.pingsRepo = S3AutoPingsRepository(awsClient: sharedContext.awsClient, logger: context.logger)
3148
}
3249

33-
func handle(
34-
_ event: APIGatewayV2Request,
35-
context: LambdaContext
36-
) async -> APIGatewayV2Response {
50+
func handle(_ event: APIGatewayV2Request) async -> APIGatewayV2Response {
3751
let newItems: S3AutoPingItems
3852
if event.rawPath.hasSuffix("all") {
3953
do {

Lambdas/Faqs/FaqsHandler.swift

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,40 @@ import Foundation
1414
#endif
1515

1616
@main
17-
struct FaqsHandler: LambdaHandler {
18-
typealias Event = APIGatewayV2Request
19-
typealias Output = APIGatewayV2Response
17+
@dynamicMemberLookup
18+
struct FaqsHandler {
19+
struct SharedContext {
20+
let awsClient: AWSClient
21+
}
22+
23+
subscript<T>(dynamicMember keyPath: KeyPath<SharedContext, T>) -> T {
24+
get {
25+
sharedContext[keyPath: keyPath]
26+
}
27+
}
2028

21-
let awsClient: AWSClient
29+
let sharedContext: SharedContext
2230
let faqsRepo: S3FaqsRepository
2331

24-
init(context: LambdaInitializationContext) async {
32+
static func main() async throws {
2533
let httpClient = HTTPClient(
26-
eventLoopGroupProvider: .shared(context.eventLoop),
34+
eventLoopGroupProvider: .shared(Lambda.defaultEventLoop),
2735
configuration: .forPenny
2836
)
2937
let awsClient = AWSClient(httpClient: httpClient)
30-
self.awsClient = awsClient
31-
self.faqsRepo = S3FaqsRepository(awsClient: awsClient, logger: context.logger)
38+
let sharedContext = SharedContext(awsClient: awsClient)
39+
try await LambdaRuntime { (event: APIGatewayV2Request, context: LambdaContext) in
40+
let handler = FaqsHandler(context: context, sharedContext: sharedContext)
41+
return await handler.handle(event)
42+
}.run()
43+
}
44+
45+
init(context: LambdaContext, sharedContext: SharedContext) {
46+
self.sharedContext = sharedContext
47+
self.faqsRepo = S3FaqsRepository(awsClient: sharedContext.awsClient, logger: context.logger)
3248
}
3349

34-
func handle(
35-
_ event: APIGatewayV2Request,
36-
context: LambdaContext
37-
) async -> APIGatewayV2Response {
50+
func handle(_ event: APIGatewayV2Request) async -> APIGatewayV2Response {
3851
let request: FaqsRequest
3952
do {
4053
request = try event.decode()

Lambdas/GHHooks/GHHooksHandler.swift

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,69 +18,82 @@ import Foundation
1818
#endif
1919

2020
@main
21-
struct GHHooksHandler: LambdaHandler {
22-
typealias Event = APIGatewayV2Request
23-
typealias Output = APIGatewayV2Response
21+
@dynamicMemberLookup
22+
struct GHHooksHandler {
23+
struct SharedContext {
24+
let httpClient: HTTPClient
25+
let githubClient: Client
26+
let awsClient: AWSClient
27+
let secretsRetriever: SecretsRetriever
28+
}
29+
30+
subscript<T>(dynamicMember keyPath: KeyPath<SharedContext, T>) -> T {
31+
get {
32+
sharedContext[keyPath: keyPath]
33+
}
34+
}
2435

25-
let httpClient: HTTPClient
26-
let githubClient: Client
27-
let secretsRetriever: SecretsRetriever
36+
let sharedContext: SharedContext
2837
let messageLookupRepo: any MessageLookupRepo
2938
let logger: Logger
3039

3140
/// We don't do this in the initializer to avoid a possible unnecessary
3241
/// `secretsRetriever.getSecret()` call which costs $$$.
3342
var discordClient: any DiscordClient {
3443
get async throws {
35-
let botToken = try await secretsRetriever.getSecret(arnEnvVarKey: "BOT_TOKEN_ARN")
36-
return await DefaultDiscordClient(httpClient: httpClient, token: botToken)
44+
let botToken = try await self.secretsRetriever.getSecret(arnEnvVarKey: "BOT_TOKEN_ARN")
45+
return await DefaultDiscordClient(httpClient: self.httpClient, token: botToken)
3746
}
3847
}
3948

40-
init(context: LambdaInitializationContext) async throws {
41-
self.logger = context.logger
42-
/// We can remove this if/when the lambda runtime gets support for
43-
/// bootstrapping the logging system which it appears to not have.
44-
DiscordGlobalConfiguration.makeLogger = { _ in context.logger }
45-
46-
self.httpClient = HTTPClient(
47-
eventLoopGroupProvider: .shared(context.eventLoop),
49+
static func main() async throws {
50+
let httpClient = HTTPClient(
51+
eventLoopGroupProvider: .shared(Lambda.defaultEventLoop),
4852
configuration: .forPenny
4953
)
50-
51-
let awsClient = AWSClient(httpClient: self.httpClient)
52-
self.secretsRetriever = SecretsRetriever(awsClient: awsClient, logger: logger)
53-
54+
let awsClient = AWSClient(httpClient: httpClient)
55+
let secretsRetriever = SecretsRetriever(awsClient: awsClient, logger: Logger(label: "GHHooksHandler"))
5456
let authenticator = Authenticator(
5557
secretsRetriever: secretsRetriever,
5658
httpClient: httpClient,
57-
logger: logger
59+
logger: Logger(label: "GitHubClient.Authenticator")
5860
)
5961

60-
self.githubClient = try .makeForGitHub(
62+
let githubClient = try Client.makeForGitHub(
6163
httpClient: httpClient,
6264
authorization: .computedBearer { isRetry in
6365
try await authenticator.generateAccessToken(
6466
forceRefreshToken: isRetry
6567
)
6668
},
67-
logger: logger
69+
logger: Logger(label: "GitHubClient")
70+
)
71+
let sharedContext = SharedContext(
72+
httpClient: httpClient,
73+
githubClient: githubClient,
74+
awsClient: awsClient,
75+
secretsRetriever: secretsRetriever
6876
)
77+
try await LambdaRuntime { (event: APIGatewayV2Request, context: LambdaContext) in
78+
let handler = try GHHooksHandler(context: context, sharedContext: sharedContext)
79+
return try await handler.handle(event)
80+
}.run()
81+
}
6982

83+
init(context: LambdaContext, sharedContext: SharedContext) throws {
84+
self.sharedContext = sharedContext
85+
self.logger = context.logger
7086
self.messageLookupRepo = DynamoMessageRepo(
71-
awsClient: awsClient,
87+
awsClient: sharedContext.awsClient,
7288
logger: logger
7389
)
7490

75-
context.logger.trace("Handler did initialize")
91+
self.logger.trace("Handler did initialize")
7692
}
7793

78-
func handle(
79-
_ request: APIGatewayV2Request,
80-
context: LambdaContext
81-
) async throws -> APIGatewayV2Response {
94+
func handle(_ request: APIGatewayV2Request) async throws -> APIGatewayV2Response {
8295
do {
83-
return try await handleThrowing(request, context: context)
96+
return try await handleThrowing(request)
8497
} catch {
8598
do {
8699
/// Report to Discord server for easier notification of maintainers
@@ -130,10 +143,7 @@ struct GHHooksHandler: LambdaHandler {
130143
}
131144
}
132145

133-
func handleThrowing(
134-
_ request: APIGatewayV2Request,
135-
context: LambdaContext
136-
) async throws -> APIGatewayV2Response {
146+
func handleThrowing(_ request: APIGatewayV2Request) async throws -> APIGatewayV2Response {
137147
logger.debug(
138148
"Got request",
139149
metadata: [
@@ -172,21 +182,21 @@ struct GHHooksHandler: LambdaHandler {
172182
context: .init(
173183
eventName: eventName,
174184
event: event,
175-
httpClient: httpClient,
176-
discordClient: discordClient,
177-
githubClient: githubClient,
185+
httpClient: self.httpClient,
186+
discordClient: self.discordClient,
187+
githubClient: self.githubClient,
178188
renderClient: RenderClient(
179189
renderer: try .forGHHooks(
180-
httpClient: httpClient,
181-
logger: logger
190+
httpClient: self.httpClient,
191+
logger: self.logger
182192
)
183193
),
184194
messageLookupRepo: self.messageLookupRepo,
185195
usersService: ServiceFactory.makeUsersService(
186-
httpClient: httpClient,
196+
httpClient: self.httpClient,
187197
apiBaseURL: apiBaseURL
188198
),
189-
logger: logger
199+
logger: self.logger
190200
)
191201
).handle()
192202

@@ -201,7 +211,7 @@ struct GHHooksHandler: LambdaHandler {
201211
throw Errors.headerNotFound(name: "x-hub-signature-256", headers: request.headers)
202212
}
203213
let body = Data((request.body ?? "").utf8)
204-
let secret = try await secretsRetriever.getSecret(arnEnvVarKey: "WH_SECRET_ARN")
214+
let secret = try await self.secretsRetriever.getSecret(arnEnvVarKey: "WH_SECRET_ARN")
205215
try Verifier.verifyWebhookSignature(
206216
signatureHeader: signature,
207217
requestBody: body,

0 commit comments

Comments
 (0)