Skip to content

Commit

Permalink
less/better preconditions + Add __DO_NOT_USE_THIS_CASE to Endpoint enums
Browse files Browse the repository at this point in the history
  • Loading branch information
MahdiBM committed May 12, 2024
1 parent 52fe131 commit 8e06b82
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 23 deletions.
28 changes: 24 additions & 4 deletions Plugins/GenerateAPIEndpointsExec/generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ var urlPrefix: String {
"""

let noEncodeParamSuffixes = ["code", "Token"]
let doNotUseThisCaseDeclaration = """
/// This case serves as a way of discouraging exhaustive switch statements
case __DO_NOT_USE_THIS_CASE
"""
let doNotUseThisCaseCrash = """
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
"""

let _url = grouped.flatMap(\.value).map { info in
let (name, params) = info.info.makeIterativeCase()
Expand Down Expand Up @@ -66,8 +74,9 @@ public var url: String {
let suffix: String
switch self {
\(_url.indent())
\(doNotUseThisCaseCrash.indent())
}
return urlPrefix + suffix
return self.urlPrefix + suffix
}
"""

Expand Down Expand Up @@ -116,8 +125,9 @@ public var urlDescription: String {
let suffix: String
switch self {
\(_urlDescription.indent())
\(doNotUseThisCaseCrash.indent())
}
return urlPrefix + suffix
return self.urlPrefix + suffix
}
"""

Expand All @@ -129,6 +139,7 @@ let methodsString = """
public var httpMethod: HTTPMethod {
switch self {
\(_methods.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand All @@ -141,6 +152,7 @@ let countsAgainstGlobalRateLimitString = """
public var countsAgainstGlobalRateLimit: Bool {
switch self {
\(_countsAgainstGlobalRateLimit.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand All @@ -155,6 +167,7 @@ let requiresAuthorizationHeaderString = """
public var requiresAuthorizationHeader: Bool {
switch self {
\(_requiresAuthorizationHeader.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand All @@ -178,6 +191,7 @@ let parametersString = """
public var parameters: [String] {
switch self {
\(_parameters.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand Down Expand Up @@ -209,6 +223,7 @@ let descriptionString = """
public var description: String {
switch self {
\(_description.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand All @@ -221,6 +236,7 @@ let idString = """
public var id: Int {
switch self {
\(_id.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand Down Expand Up @@ -251,6 +267,7 @@ let cacheableDescriptionString = """
public var description: String {
switch self {
\(_cacheableDescription.indent())
\(doNotUseThisCaseCrash.indent())
}
}
"""
Expand All @@ -265,6 +282,7 @@ let cacheableInitString = """
init? (endpoint: APIEndpoint) {
switch endpoint {
\(_cacheableInit.indent())
\(doNotUseThisCaseCrash.indent())
default: return nil
}
}
Expand All @@ -280,11 +298,12 @@ let result = """
import DiscordModels
import NIOHTTP1
/// UNSTABLE ENUM, DO NOT USE EXHAUSTIVE SWITCH STATEMENTS.
public enum APIEndpoint: Endpoint {
\(cases.indent())
\(doNotUseThisCaseDeclaration.indent())
\(urlPrefixString.indent())
\(urlString.indent())
Expand All @@ -304,11 +323,12 @@ public enum APIEndpoint: Endpoint {
\(descriptionString.indent())
}
/// UNSTABLE ENUM, DO NOT USE EXHAUSTIVE SWITCH STATEMENTS.
public enum CacheableAPIEndpointIdentity: Int, Sendable, Hashable, CustomStringConvertible {
\(cacheableCases.indent())
\(doNotUseThisCaseDeclaration.indent())
\(cacheableDescriptionString.indent())
\(cacheableInitString.indent())
Expand Down
10 changes: 7 additions & 3 deletions Sources/DiscordGateway/DiscordCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,17 @@ public actor DiscordCache {
}
}

func calculateCheckForLimitEvery() -> Int {
/// Checks for the limit interval and MODIFIES `itemsLimit` to `disabled` if appropriate.
mutating func calculateCheckForLimitEvery() -> Int {
switch self {
case .disabled: return 1 /// Doesn't matter
case let .constant(limit):
let powed = pow(1/2, Double(limit))
return max(10, Int(powed))
case let .custom(custom):
guard let minimum = custom.map(\.value).min() else {
fatalError("It's meaningless for 'ItemsLimit.custom' to be empty. Please use `ItemsLimit.disabled` instead")
assert(false, "It's meaningless for 'ItemsLimit.custom' to be empty. Please use `ItemsLimit.disabled` instead")
self = .disabled
}
let powed = pow(1/2, Double(minimum))
return max(10, Int(powed))
Expand Down Expand Up @@ -350,8 +352,10 @@ public actor DiscordCache {
)
self.requestMembers = requestAllMembers
self.messageCachingPolicy = messageCachingPolicy
self.itemsLimit = itemsLimit
var itemsLimit = itemsLimit
/// Checks for the limit interval and MODIFIES `itemsLimit` to `disabled` if appropriate.
self.checkForLimitEvery = itemsLimit.calculateCheckForLimitEvery()
self.itemsLimit = itemsLimit
self.storage = storage

Task {
Expand Down
2 changes: 2 additions & 0 deletions Sources/DiscordHTTP/ClientCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ actor ClientCache {
case .loose(let endpoint):
hasher.combine(2)
endpoint.hash(into: &hasher)
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
for param in parameters {
hasher.combine(param)
Expand Down
17 changes: 10 additions & 7 deletions Sources/DiscordHTTP/ClientConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ public struct ClientConfiguration: Sendable {
return ttl.components == (0, 0) ? nil : ttl
case .loose:
return self.looseEndpointsTTL
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}
}
Expand Down Expand Up @@ -205,15 +207,11 @@ public struct ClientConfiguration: Sendable {
public var statuses: Set<HTTPResponseStatus> {
get { self._statuses }
set {
#if DEBUG
precondition(
assert(
newValue.allSatisfy({ $0.code >= 400 }),
"Status codes less than 400 don't need retrying. This could cause problems"
)
self._statuses = newValue
#else
self._statuses = newValue.filter({ $0.code >= 400 })
#endif
}
}

Expand All @@ -236,8 +234,13 @@ public struct ClientConfiguration: Sendable {
/// - backoff: The backoff configuration, to wait a some amount of time
/// _after_ a failed request.
public init(
statuses: Set<HTTPResponseStatus> = [.tooManyRequests, .internalServerError, .badGateway],
maxRetries: Int = 1,
statuses: Set<HTTPResponseStatus> = [
.tooManyRequests,
.internalServerError,
.badGateway,
.gatewayTimeout
],
maxRetries: Int = 3,
backoff: Backoff? = .default
) {
self.maxRetries = maxRetries
Expand Down
32 changes: 28 additions & 4 deletions Sources/DiscordHTTP/Endpoints/APIEndpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import DiscordModels
import NIOHTTP1

/// UNSTABLE ENUM, DO NOT USE EXHAUSTIVE SWITCH STATEMENTS.
public enum APIEndpoint: Endpoint {

// MARK: Polls
Expand Down Expand Up @@ -294,6 +293,9 @@ public enum APIEndpoint: Endpoint {
case deleteWebhookByToken(webhookId: WebhookSnowflake, webhookToken: String)
case deleteWebhookMessage(webhookId: WebhookSnowflake, webhookToken: String, messageId: MessageSnowflake)

/// This case serves as a way of discouraging exhaustive switch statements
case __DO_NOT_USE_THIS_CASE

var urlPrefix: String {
"https://discord.com/api/v\(DiscordGlobalConfiguration.apiVersion)/"
}
Expand Down Expand Up @@ -915,8 +917,10 @@ public enum APIEndpoint: Endpoint {
let webhookId = webhookId.rawValue
let messageId = messageId.rawValue
suffix = "webhooks/\(webhookId)/\(webhookToken)/messages/\(messageId)"
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
return urlPrefix + suffix
return self.urlPrefix + suffix
}

public var urlDescription: String {
Expand Down Expand Up @@ -1543,8 +1547,10 @@ public enum APIEndpoint: Endpoint {
let webhookToken = webhookToken.urlPathEncoded().hash
let messageId = messageId.rawValue
suffix = "webhooks/\(webhookId)/\(webhookToken)/messages/\(messageId)"
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
return urlPrefix + suffix
return self.urlPrefix + suffix
}

public var httpMethod: HTTPMethod {
Expand Down Expand Up @@ -1733,6 +1739,8 @@ public enum APIEndpoint: Endpoint {
case .deleteWebhook: return .DELETE
case .deleteWebhookByToken: return .DELETE
case .deleteWebhookMessage: return .DELETE
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}

Expand Down Expand Up @@ -1922,6 +1930,8 @@ public enum APIEndpoint: Endpoint {
case .deleteWebhook: return true
case .deleteWebhookByToken: return true
case .deleteWebhookMessage: return true
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}

Expand Down Expand Up @@ -2111,6 +2121,8 @@ public enum APIEndpoint: Endpoint {
case .deleteWebhook: return true
case .deleteWebhookByToken: return false
case .deleteWebhookMessage: return false
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}

Expand Down Expand Up @@ -2484,6 +2496,8 @@ public enum APIEndpoint: Endpoint {
return [webhookId.rawValue, webhookToken]
case let .deleteWebhookMessage(webhookId, webhookToken, messageId):
return [webhookId.rawValue, webhookToken, messageId.rawValue]
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}

Expand Down Expand Up @@ -2673,6 +2687,8 @@ public enum APIEndpoint: Endpoint {
case .deleteWebhook: return 182
case .deleteWebhookByToken: return 183
case .deleteWebhookMessage: return 184
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}

Expand Down Expand Up @@ -3046,11 +3062,12 @@ public enum APIEndpoint: Endpoint {
return "deleteWebhookByToken(webhookId.rawValue: \(webhookId.rawValue), webhookToken: \(webhookToken))"
case let .deleteWebhookMessage(webhookId, webhookToken, messageId):
return "deleteWebhookMessage(webhookId.rawValue: \(webhookId.rawValue), webhookToken: \(webhookToken), messageId.rawValue: \(messageId.rawValue))"
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}
}

/// UNSTABLE ENUM, DO NOT USE EXHAUSTIVE SWITCH STATEMENTS.
public enum CacheableAPIEndpointIdentity: Int, Sendable, Hashable, CustomStringConvertible {

// MARK: Polls
Expand Down Expand Up @@ -3228,6 +3245,9 @@ public enum CacheableAPIEndpointIdentity: Int, Sendable, Hashable, CustomStringC
case getWebhookMessage
case listChannelWebhooks

/// This case serves as a way of discouraging exhaustive switch statements
case __DO_NOT_USE_THIS_CASE

public var description: String {
switch self {
case .listPollAnswerVoters: return "listPollAnswerVoters"
Expand Down Expand Up @@ -3305,6 +3325,8 @@ public enum CacheableAPIEndpointIdentity: Int, Sendable, Hashable, CustomStringC
case .getWebhookByToken: return "getWebhookByToken"
case .getWebhookMessage: return "getWebhookMessage"
case .listChannelWebhooks: return "listChannelWebhooks"
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
}
}

Expand Down Expand Up @@ -3385,6 +3407,8 @@ public enum CacheableAPIEndpointIdentity: Int, Sendable, Hashable, CustomStringC
case .getWebhookByToken: self = .getWebhookByToken
case .getWebhookMessage: self = .getWebhookMessage
case .listChannelWebhooks: self = .listChannelWebhooks
case .__DO_NOT_USE_THIS_CASE:
fatalError("If the case name wasn't already clear enough: '__DO_NOT_USE_THIS_CASE' MUST NOT be used")
default: return nil
}
}
Expand Down

0 comments on commit 8e06b82

Please sign in to comment.