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
90
91
92
93
94
95
96
97
98
99
100
101
102
|
import Foundation
// MARK: - Response types (file-private to avoid @MainActor Decodable issues)
private struct CommitResponse: Decodable, Sendable {
let repository: CommitRepository?
}
private struct CommitRepository: Decodable, Sendable {
// swiftlint:disable:next identifier_name
let revparse_single: CommitDetail
}
// MARK: - View Model
@Observable
@MainActor
final class CommitDetailViewModel {
let repositoryRid: String
let service: SRHTService
private let client: SRHTClient
private(set) var commit: CommitDetail?
private(set) var isLoading = false
var error: String?
init(repositoryRid: String, service: SRHTService, commitId: String, client: SRHTClient) {
self.repositoryRid = repositoryRid
self.service = service
self.commitId = commitId
self.client = client
}
private let commitId: String
// MARK: - Query
private static let query = """
query commit($rid: ID!, $id: String!) {
repository(rid: $rid) {
revparse_single(revspec: $id) {
id
shortId
author { name email time }
committer { name email time }
message
diff
trailers { name value }
parents { id shortId author { name } }
tree {
entries {
results { id name mode object { type id shortId } }
cursor
}
}
}
}
}
"""
func loadCommit() async {
guard !isLoading else { return }
isLoading = true
error = nil
do {
let result = try await executeWithRetry()
commit = result.repository?.revparse_single
} catch {
self.error = error.localizedDescription
}
isLoading = false
}
/// Execute the commit query, retrying once after a 1-second delay on 502/503.
private func executeWithRetry() async throws -> CommitResponse {
do {
return try await client.execute(
service: service,
query: Self.query,
variables: [
"rid": repositoryRid,
"id": commitId
],
responseType: CommitResponse.self
)
} catch let SRHTError.httpError(code) where code == 502 || code == 503 {
try await Task.sleep(for: .seconds(1))
return try await client.execute(
service: service,
query: Self.query,
variables: [
"rid": repositoryRid,
"id": commitId
],
responseType: CommitResponse.self
)
}
}
}
|