Emcee

Форк
0
/
ScheduleTestsEndpoint.swift 
94 строки · 3.9 Кб
1
import BalancingBucketQueue
2
import CommonTestModels
3
import Dispatch
4
import Foundation
5
import EmceeLogging
6
import QueueModels
7
import RESTInterfaces
8
import RESTMethods
9
import RESTServer
10
import SynchronousWaiter
11
import WorkerAlivenessModels
12
import WorkerAlivenessProvider
13
import WorkerCapabilities
14
import UniqueIdentifierGenerator
15

16
public final class ScheduleTestsEndpoint: RESTEndpoint {
17
    private let testsEnqueuer: TestsEnqueuer
18
    private let uniqueIdentifierGenerator: UniqueIdentifierGenerator
19
    private let waitForCapableWorkerTimeout: TimeInterval
20
    private let workerAlivenessProvider: WorkerAlivenessProvider
21
    private let workerCapabilityConstraintResolver = WorkerCapabilityConstraintResolver()
22
    private let workerCapabilitiesStorage: WorkerCapabilitiesStorage
23
    public let path: RESTPath = RESTMethod.scheduleTests
24
    public let requestIndicatesActivity = true
25
    
26
    public init(
27
        testsEnqueuer: TestsEnqueuer,
28
        uniqueIdentifierGenerator: UniqueIdentifierGenerator,
29
        waitForCapableWorkerTimeout: TimeInterval,
30
        workerAlivenessProvider: WorkerAlivenessProvider,
31
        workerCapabilitiesStorage: WorkerCapabilitiesStorage
32
    ) {
33
        self.testsEnqueuer = testsEnqueuer
34
        self.uniqueIdentifierGenerator = uniqueIdentifierGenerator
35
        self.waitForCapableWorkerTimeout = waitForCapableWorkerTimeout
36
        self.workerAlivenessProvider = workerAlivenessProvider
37
        self.workerCapabilitiesStorage = workerCapabilitiesStorage
38
    }
39
    
40
    public func handle(payload: ScheduleTestsPayload) throws -> ScheduleTestsResponse {
41
        try waitForAnySuitableWorker(payload: payload)
42
        
43
        try testsEnqueuer.enqueue(
44
            configuredTestEntries: payload.similarlyConfiguredTestEntries.configuredTestEntries,
45
            testSplitter: payload.scheduleStrategy.testSplitter,
46
            prioritizedJob: payload.prioritizedJob
47
        )
48
        return .scheduledTests
49
    }
50
    
51
    private func waitForAnySuitableWorker(payload: ScheduleTestsPayload) throws {
52
        guard !payload.similarlyConfiguredTestEntries.testEntries.isEmpty else { return }
53
        
54
        let configurationHasAllRequirementsMet: () -> Bool = {
55
            self.workerAlivenessProvider.workerAliveness.contains(
56
                where: { (item: (workerId: WorkerId, aliveness: WorkerAliveness)) -> Bool in
57
                    guard item.aliveness.isInWorkingCondition else { return false }
58
                    return self.workerCapabilityConstraintResolver.requirementsSatisfied(
59
                        requirements: payload.similarlyConfiguredTestEntries.testEntryConfiguration.workerCapabilityRequirements,
60
                        workerCapabilities: self.workerCapabilitiesStorage.workerCapabilities(
61
                            forWorkerId: item.workerId
62
                        )
63
                    )
64
                }
65
            )
66
        }
67
        
68
        try SynchronousWaiter().mapErrorIfTimeout(
69
            work: { waiter in
70
                try waiter.waitWhile(
71
                    timeout: waitForCapableWorkerTimeout,
72
                    description: "Test entry configuration requirements can be satisfied"
73
                ) {
74
                    configurationHasAllRequirementsMet() == false
75
                }
76
            },
77
            timeoutToErrorTransformation: { timeout -> Error in
78
                NoSuitableWorkerAppearedError(
79
                    testEntryConfiguration: payload.similarlyConfiguredTestEntries.testEntryConfiguration,
80
                    timeout: timeout.value
81
                )
82
            }
83
        )
84
    }
85
}
86

87
private struct NoSuitableWorkerAppearedError: Error, CustomStringConvertible {
88
    let testEntryConfiguration: TestEntryConfiguration
89
    let timeout: TimeInterval
90
    
91
    var description: String {
92
        "Some worker requirements cannot be met after waiting for \(timeout.loggableInSeconds()) for any worker with suitable capabilities to appear: \(testEntryConfiguration)"
93
    }
94
}
95

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.