У меня есть приложение командной строки, которое выполняет следующие действия:
- загружает RSS-канал с торрент-ссылками
- сохраняет его в базе данных sqlite и помечает их как «добавлено» или «игнорируется»
- подключается к серверу передачи (в моей локальной сети)
- загружает элементы из sqlite, помеченные как «добавленные», и добавляет на сервер передачи
выше отлично работает в режиме отладки. Однако, когда я создаю релиз и пытаюсь запустить его напрямую или из launchd, время ожидания всегда истекает. Наиболее подходящий код находится в main.swift
, который идет ниже.
private func getTransmissionClient() -> Transmission? {
let client = Transmission(
baseURL: serverConfig.server,
username: serverConfig.username,
password: serverConfig.password)
var cancellables = Set<AnyCancellable>()
let group = DispatchGroup()
group.enter()
print("[INFO] Connecting to client")
client.request(.rpcVersion)
.sink(
receiveCompletion: { _ in group.leave() },
receiveValue: { rpcVersion in
print("[INFO]: Successfully Connected! RPC Version: \(rpcVersion)")
})
.store(in: &cancellables)
let wallTimeout = DispatchWallTime.now() +
DispatchTimeInterval.seconds(serverConfig.secondsTimeout ?? 15)
let res = group.wait(wallTimeout: wallTimeout)
if res == DispatchTimeoutResult.success {
return client
} else {
return nil
}
}
public func updateTransmission() throws {
print("[INFO] [\(Date())] Starting Transmission Update")
let clientOpt = getTransmissionClient()
guard let client = clientOpt else {
print("[ERROR] Failed to connect to transmission client")
exit(1)
}
var cancellables = Set<AnyCancellable>()
let items = try store.getPendingDownload()
print("[INFO] [\(Date())] Adding \(items.count) new items to transmission")
let group = DispatchGroup()
for item in items {
let linkComponents = "\(item.link)".components(separatedBy: "&")
assert(linkComponents.count > 0, "Link seems wrong")
group.enter()
client.request(.add(url: item.link))
.sink(receiveCompletion: { completion in
if case let .failure(error) = completion {
print("[Failure] \(item.title)")
print("[Failure] Details: \(error)")
}
group.leave()
}, receiveValue: { _ in
print("[Success] \(item.title)")
do {
try self.store.update(item: item, with: .downloaded)
} catch {
print("[Error] Couldn't save new status to DB")
}
})
.store(in: &cancellables)
}
let wallTimeout = DispatchWallTime.now() +
DispatchTimeInterval.seconds(serverConfig.secondsTimeout ?? 15)
let res = group.wait(wallTimeout: wallTimeout)
if res == DispatchTimeoutResult.success {
print("Tasks successfully submitted")
} else {
print("Timed out")
exit(1)
}
}
Как ни странно, код, казалось, работал нормально до того, как я добавил базу данных. Группа DispatchGroup уже была там, как и клиент Transmission-Swift. Полагаю, что-то, что я сделал, "оптимизируется" компилятором? Это просто предположение, хотя после просмотра некоторых других вопросов о StackOverflow, но я все еще не понимаю его.
Я использую macOS 10.15 и Swift 5.2.2.
Полный код доступен в github (ссылка на конкретный c коммит с ошибкой)