Ga naar inhoud

Services

Vapor's Application en Request zijn gebouwd om uitgebreid te worden door uw applicatie en pakketten van derden. Nieuwe functionaliteit toegevoegd aan deze types worden vaak services genoemd.

Read Only

Het eenvoudigste type service is read-only. Deze diensten bestaan uit berekende variabelen of methoden die worden toegevoegd aan een toepassing of verzoek.

import Vapor

struct MyAPI {
    let client: Client

    func foos() async throws -> [String] { ... }
}

extension Request {
    var myAPI: MyAPI {
        .init(client: self.client)
    }
}

Alleen-lezen diensten kunnen afhankelijk zijn van reeds bestaande diensten, zoals client in dit voorbeeld. Zodra de extensie is toegevoegd, kan uw aangepaste service worden gebruikt als elke andere eigenschap op aanvraag.

req.myAPI.foos()

Writable

Services die state of configuratie nodig hebben kunnen Application en Request opslag gebruiken om data op te slaan. Laten we aannemen dat je de volgende MyConfiguration struct wilt toevoegen aan je applicatie.

struct MyConfiguration {
    var apiKey: String
}

Om opslag te gebruiken, moet je een StorageKey declareren.

struct MyConfigurationKey: StorageKey {
    typealias Value = MyConfiguration
}

Dit is een lege struct met een Value typealias die aangeeft welk type wordt opgeslagen. Door een leeg type als sleutel te gebruiken, kun je bepalen welke code toegang heeft tot de waarde in de opslag. Als het type intern of privaat is, kan alleen jouw code de waarde in de opslag wijzigen.

Voeg tenslotte een uitbreiding toe aan Application voor het verkrijgen en instellen van de MyConfiguration struct.

extension Application {
    var myConfiguration: MyConfiguration? {
        get {
            self.storage[MyConfigurationKey.self]
        }
        set {
            self.storage[MyConfigurationKey.self] = newValue
        }
    }
}

Zodra de uitbreiding is toegevoegd, kunt u myConfiguration gebruiken als een normale eigenschap van Application.

app.myConfiguration = .init(apiKey: ...)
print(app.myConfiguration?.apiKey)

Lifecycle

Vapor's Application staat u toe om lifecycle handlers te registreren. Deze laten u inhaken op gebeurtenissen zoals opstarten en afsluiten.

// Drukt "hello" af tijdens het opstarten.
struct Hello: LifecycleHandler {
    // Wordt aangeroepen voordat de toepassing opstart.
    func willBoot(_ app: Application) throws {
        app.logger.info("Hello!")
    }

    // Wordt aangeroepen nadat de applicatie is opgestart.
    func didBoot(_ app: Application) throws {
        app.logger.info("Server is running")
    }

    // Wordt aangeroepen voordat de applicatie wordt afgesloten.
    func shutdown(_ app: Application) {
        app.logger.info("Goodbye!")
    }
}

// Voeg levenscyclus handler toe.
app.lifecycle.use(Hello())

Locks

Vapor's Application bevat mogelijkheden om code te synchroniseren met behulp van locks. Door een LockKey te declareren, kun je een uniek, gedeeld slot krijgen om de toegang tot je code te synchroniseren.

struct TestKey: LockKey { }

let test = app.locks.lock(for: TestKey.self)
test.withLock {
    // Doe iets.
}

Elke oproep aan lock(for:) met dezelfde LockKey zal hetzelfde slot teruggeven. Deze methode is thread-safe.

Voor een applicatie-breed slot, kun je app.sync gebruiken.

app.sync.withLock {
    // Doe iets.
}

Verzoek

Services die bedoeld zijn om te worden gebruikt in route handlers moeten worden toegevoegd aan Request. Request services moeten de logger en de event loop van het verzoek gebruiken. Het is belangrijk dat een verzoek op dezelfde event loop blijft, anders wordt een assertion geraakt wanneer het antwoord wordt teruggestuurd naar Vapor.

Als een service de event loop van het request moet verlaten om werk te doen, moet hij ervoor zorgen dat hij terugkeert naar de event loop voordat hij klaar is. Dit kan gedaan worden met de hop(to:) op EventLoopFuture.

Request diensten die toegang nodig hebben tot applicatie diensten, zoals configuraties, kunnen req.application gebruiken. Let op de thread-safety bij het benaderen van de applicatie vanuit een route handler. Over het algemeen mogen alleen leesbewerkingen worden uitgevoerd door requests. Schrijf operaties moeten worden beschermd door locks.