generated from Apodini/Template-Repository
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f509773
commit e55652f
Showing
23 changed files
with
1,011 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,50 @@ | ||
// swift-tools-version:5.5 | ||
|
||
// | ||
// This source file is part of the Apodini open source project | ||
// | ||
// SPDX-FileCopyrightText: 2021 Paul Schmiedmayer and the project authors (see CONTRIBUTORS.md) <paul.schmiedmayer@tum.de> | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
|
||
let package = Package( | ||
name: "ApodiniTemplate", | ||
name: "ApodiniSustainability", | ||
platforms: [ | ||
.macOS(.v11) | ||
.macOS(.v12) | ||
], | ||
products: [ | ||
.library(name: "ApodiniTemplate", targets: ["ApodiniTemplate"]) | ||
// Products define the executables and libraries a package produces, and make them visible to other packages. | ||
.library( | ||
name: "ApodiniSustainability", | ||
targets: ["ApodiniSustainability"]), | ||
.executable( | ||
name: "ApodiniSustainabilityDemo", | ||
targets: ["ApodiniSustainabilityDemo"]) | ||
], | ||
dependencies: [ | ||
// Dependencies declare other packages that this package depends on. | ||
// .package(url: /* package url */, from: "1.0.0"), | ||
.package(url: "https://github.com/Apodini/Apodini.git", .upToNextMinor(from: "0.9.0")), | ||
.package(url: "https://github.com/Apodini/ApodiniDocumentExport.git", .upToNextMinor(from: "0.1.0")), | ||
], | ||
targets: [ | ||
.target(name: "ApodiniTemplate"), | ||
// Targets are the basic building blocks of a package. A target can define a module or a test suite. | ||
// Targets can depend on other targets in this package, and on products in packages this package depends on. | ||
.target( | ||
name: "ApodiniSustainability", | ||
dependencies: [ | ||
.product(name: "Apodini", package: "Apodini"), | ||
.product(name: "ApodiniNetworking", package: "Apodini"), | ||
.product(name: "ApodiniDocumentExport", package: "ApodiniDocumentExport") | ||
]), | ||
.executableTarget( | ||
name: "ApodiniSustainabilityDemo", | ||
dependencies: [ | ||
.product(name: "Apodini", package: "Apodini"), | ||
.product(name: "ApodiniREST", package: "Apodini"), | ||
.target(name: "ApodiniSustainability") | ||
]), | ||
.testTarget( | ||
name: "ApodiniTemplateTests", | ||
name: "ApodiniSustainabilityTests", | ||
dependencies: [ | ||
.target(name: "ApodiniTemplate") | ||
] | ||
) | ||
.target(name: "ApodiniSustainability"), | ||
.product(name: "XCTApodiniNetworking", package: "Apodini") | ||
]), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# ``ApodiniSustainability`` |
100 changes: 100 additions & 0 deletions
100
Sources/ApodiniSustainability/ApodiniSustainabilityInterfaceExporter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import Apodini | ||
import ApodiniDocumentExport | ||
import ApodiniNetworking | ||
@_implementationOnly import Logging | ||
|
||
final class ApodiniSustainabilityInterfaceExporter: InterfaceExporter { | ||
|
||
private let app: Application | ||
private let configuration: SustainabilityDocumentConfiguration | ||
private var services: [String: Service] = .init() | ||
private let logger = Logger(label: "org.apodini.sustainability") | ||
|
||
init(_ app: Application, configuration: SustainabilityDocumentConfiguration) { | ||
self.app = app | ||
self.configuration = configuration | ||
} | ||
|
||
func export<H>(_ endpoint: Endpoint<H>) -> () where H : Handler { | ||
|
||
guard let key = endpoint[Context.self].get(valueFor: ServiceIdentifierComponentMetadata.self) else { return } | ||
|
||
let requirements = Requirements(responseTime: endpoint[Context.self].get(valueFor: ResponseTimeHandlerMetadata.self), instanceType: endpoint[Context.self].get(valueFor: InstanceTypeHandlerMetadata.self)) | ||
|
||
let serviceVersion = ServiceVersion(id: endpoint[AnyHandlerIdentifier.self], name: endpoint[HandlerDescription.self].rawValue, description: endpoint[Context.self].get(valueFor: HandlerDescriptionMetadata.self), requirements: requirements) | ||
|
||
let modalities: ExecutionModalities | ||
|
||
switch endpoint[Context.self].get(valueFor: ExecutionModalityHandlerMetadata.self) { | ||
case .highPerformance: | ||
modalities = ExecutionModalities(highPerformance: serviceVersion) | ||
case .lowPower: | ||
modalities = ExecutionModalities(lowPower: serviceVersion) | ||
default: | ||
modalities = ExecutionModalities(standard: serviceVersion) | ||
} | ||
|
||
let optional : Bool? = endpoint[Context.self].get(valueFor: OptionalComponentMetadata.self) | ||
|
||
services.merge([key : Service( | ||
id: key, | ||
name: key.replacingOccurrences(of: "-", with: " ").capitalized(with: nil), | ||
description: String.init(), | ||
optional: optional, | ||
modalities: modalities | ||
)]) { current, new in | ||
var service = current | ||
service.modalities = service.modalities.merge(with: new.modalities) | ||
if new.optional ?? false { | ||
service.optional = true | ||
} | ||
return service | ||
} | ||
} | ||
|
||
func export<H>(blob endpoint: Endpoint<H>) -> () where H : Handler, H.Response.Content == Blob { | ||
export(endpoint) | ||
} | ||
|
||
func finishedExporting(_ webService: WebServiceModel) { | ||
|
||
let document = SustainabilityDocument( | ||
serverPath: app.httpConfiguration.uriPrefix, | ||
version: webService.context.get(valueFor: APIVersionContextKey.self).semVerString, | ||
description: webService.context.get(valueFor: WebServiceDescriptionMetadata.self), | ||
services: [Service](services.values) | ||
) | ||
|
||
app.storage.set(SustainabilityDocumentStorageKey.self, to: document) | ||
|
||
guard let options = configuration.exportOptions else { | ||
return logger.notice("No configuration provided to handle the ApodiniSustainability document of the current version") | ||
} | ||
|
||
if let directory = options.directory { | ||
do { | ||
let filePath = try document.write(at: directory, outputFormat: options.format, fileName: "sustainability_\(document.version)") | ||
logger.info("ApodiniSustainability document exported at \(filePath) in \(options.format.rawValue)") | ||
} catch { | ||
logger.error("ApodiniSustainability export at \(directory) failed with error: \(error)") | ||
} | ||
} | ||
|
||
if let endpoint = options.endpoint { | ||
// app.httpServer.registerRoute(.GET, endpoint.httpPathComponents) { _ -> String in | ||
// options.format.string(of: document) | ||
// } | ||
app.httpServer.registerRoute(.GET, endpoint.httpPathComponents) { req in | ||
HTTPResponse( | ||
version: req.version, | ||
status: .ok, | ||
headers: HTTPHeaders { | ||
$0[.accessControlAllowOrigin] = .wildcard | ||
}, | ||
bodyStorage: .buffer(initialValue: options.format.string(of: document)) | ||
) | ||
} | ||
logger.info("ApodiniSustainability document served at \(endpoint) in \(options.format.rawValue) format") | ||
} | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
Sources/ApodiniSustainability/Metadata/ExecutionModalityMetadata.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import Apodini | ||
import ApodiniDocumentExport | ||
|
||
public enum ExecutionModalityOption: String, Value { | ||
case standard | ||
case highPerformance | ||
case lowPower | ||
} | ||
|
||
public struct ExecutionModalityMetadataContextKey: ContextKey { | ||
public static var defaultValue = ExecutionModalityOption.standard | ||
public typealias Value = ExecutionModalityOption | ||
} | ||
|
||
extension HandlerMetadataNamespace { | ||
/// Name definition for the ``ExecutionModalityHandlerMetadata`` | ||
public typealias ExecutionModality = ExecutionModalityHandlerMetadata | ||
} | ||
|
||
/// The ``ExecutionModalityHandlerMetadata`` can be used to describe the execution modality of a ``Handler``. | ||
/// | ||
/// The Metadata is available under the ``HandlerMetadataNamespace/ExecutionModality`` name and can be used like the following: | ||
/// ```swift | ||
/// struct ExampleHandler: Handler { | ||
/// // ... | ||
/// var metadata: Metadata { | ||
/// ExecutionModality(.highPerformance) | ||
/// } | ||
/// } | ||
/// ``` | ||
public struct ExecutionModalityHandlerMetadata: HandlerMetadataDefinition { | ||
public typealias Key = ExecutionModalityMetadataContextKey | ||
public let value: ExecutionModalityOption | ||
|
||
/// Creates a new `ExecutionModality` metadata | ||
/// - Parameter value: The execution modality option for the Component. | ||
public init(_ value: ExecutionModalityOption) { | ||
self.value = value | ||
} | ||
} | ||
|
||
extension Handler { | ||
/// A `executionModality` modifier can be used to specify the `ExecutionModalityHandlerMetadata` via a `HandlerModifier`. | ||
/// - Parameter value: The `executionModality` that is used for the `Handler` | ||
/// - Returns: The modified `Handler` with the `ExecutionModalityHandlerMetadata` added. | ||
public func executionModality(_ value: ExecutionModalityOption) -> HandlerMetadataModifier<Self> { | ||
HandlerMetadataModifier(modifies: self, with: ExecutionModalityHandlerMetadata(value)) | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
Sources/ApodiniSustainability/Metadata/InstanceTypeMetadata.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import Apodini | ||
import ApodiniDocumentExport | ||
|
||
public enum InstanceTypeOption: String, Value { | ||
case large | ||
case medium | ||
case small | ||
} | ||
|
||
public struct InstanceTypeMetadataContextKey: OptionalContextKey { | ||
public typealias Value = InstanceTypeOption | ||
} | ||
|
||
extension HandlerMetadataNamespace { | ||
/// Name definition for the ``InstanceTypeHandlerMetadata`` | ||
public typealias InstanceType = InstanceTypeHandlerMetadata | ||
} | ||
|
||
/// The ``InstanceTypeHandlerMetadata`` can be used to describe the instance type of a ``Handler``. | ||
/// | ||
/// The Metadata is available under the ``HandlerMetadataNamespace/InstanceType`` name and can be used like the following: | ||
/// ```swift | ||
/// struct ExampleHandler: Handler { | ||
/// // ... | ||
/// var metadata: Metadata { | ||
/// InstanceType(.small) | ||
/// } | ||
/// } | ||
/// ``` | ||
public struct InstanceTypeHandlerMetadata: HandlerMetadataDefinition { | ||
public typealias Key = InstanceTypeMetadataContextKey | ||
public let value: InstanceTypeOption | ||
|
||
/// Creates a new `InstanceType` metadata | ||
/// - Parameter value: The instance type option for the Component. | ||
public init(_ value: InstanceTypeOption) { | ||
self.value = value | ||
} | ||
} | ||
|
||
extension Handler { | ||
/// A `instanceType` modifier can be used to specify the `InstanceTypeHandlerMetadata` via a `HandlerModifier`. | ||
/// - Parameter value: The `instanceType` that is used for the `Handler` | ||
/// - Returns: The modified `Handler` with the `InstanceTypeHandlerMetadata` added. | ||
public func instanceType(_ value: InstanceTypeOption) -> HandlerMetadataModifier<Self> { | ||
HandlerMetadataModifier(modifies: self, with: InstanceTypeHandlerMetadata(value)) | ||
} | ||
} |
Oops, something went wrong.