feat: Adds createMany for rooms, in prep for parsing / uploading a csv file of room loads.
All checks were successful
CI / Linux Tests (push) Successful in 7m0s
All checks were successful
CI / Linux Tests (push) Successful in 7m0s
This commit is contained in:
@@ -6,16 +6,14 @@
|
|||||||
"version": "os-provided",
|
"version": "os-provided",
|
||||||
"ppa": "false"
|
"ppa": "false"
|
||||||
},
|
},
|
||||||
"ghcr.io/swift-server-community/swift-devcontainer-features/jemalloc:1": { },
|
|
||||||
"ghcr.io/swift-server-community/swift-devcontainer-features/swift-format:0": { },
|
|
||||||
"ghcr.io/swift-server-community/swift-devcontainer-features/foundationnetworking:1": {},
|
|
||||||
"ghcr.io/devcontainers-extra/features/markdownlint-cli2:1": {},
|
|
||||||
"ghcr.io/jsburckhardt/devcontainer-features/just:1": {},
|
"ghcr.io/jsburckhardt/devcontainer-features/just:1": {},
|
||||||
"ghcr.io/rocker-org/devcontainer-features/pandoc:1": {},
|
"ghcr.io/rocker-org/devcontainer-features/pandoc:1": {},
|
||||||
//"ghcr.io/devcontainers/features/docker-in-docker:2": {},
|
//"ghcr.io/devcontainers/features/docker-in-docker:2": {},
|
||||||
"ghcr.io/wxw-matt/devcontainer-features/apt:latest": {
|
"ghcr.io/wxw-matt/devcontainer-features/apt:latest": {
|
||||||
"packages": "weasyprint gnupg2 tmux"
|
"packages": "weasyprint gnupg2 tmux"
|
||||||
}
|
},
|
||||||
|
"ghcr.io/swift-server-community/swift-devcontainer-features/jemalloc:1": { },
|
||||||
|
|
||||||
},
|
},
|
||||||
"runArgs": [
|
"runArgs": [
|
||||||
"--cap-add=SYS_PTRACE",
|
"--cap-add=SYS_PTRACE",
|
||||||
@@ -23,9 +21,20 @@
|
|||||||
"seccomp=unconfined"
|
"seccomp=unconfined"
|
||||||
],
|
],
|
||||||
"remoteEnv": {
|
"remoteEnv": {
|
||||||
"TERM": "xterm-256color"
|
// Set TERM, prevents problems when "xterm-ghostty" get's passed from host,
|
||||||
|
// which causes weird typing and display problems.
|
||||||
|
"TERM": "xterm-256color",
|
||||||
|
// Less backtrace error warnings from swift.
|
||||||
|
"SWIFT_BACKTRACE": "enable=no"
|
||||||
},
|
},
|
||||||
"remoteUser": "swift",
|
"remoteUser": "swift",
|
||||||
"forwardPorts": [8080],
|
"forwardPorts": [8080],
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"type": "bind",
|
||||||
|
"source": "${localEnv:HOME}/.local/share/nvim",
|
||||||
|
"target": "/home/swift/.local/share/nvim"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ public struct DatabaseClient: Sendable {
|
|||||||
@DependencyClient
|
@DependencyClient
|
||||||
public struct Rooms: Sendable {
|
public struct Rooms: Sendable {
|
||||||
public var create: @Sendable (Room.Create) async throws -> Room
|
public var create: @Sendable (Room.Create) async throws -> Room
|
||||||
|
public var createMany: @Sendable ([Room.Create]) async throws -> [Room]
|
||||||
public var delete: @Sendable (Room.ID) async throws -> Void
|
public var delete: @Sendable (Room.ID) async throws -> Void
|
||||||
public var deleteRectangularSize:
|
public var deleteRectangularSize:
|
||||||
@Sendable (Room.ID, Room.RectangularSize.ID) async throws -> Room
|
@Sendable (Room.ID, Room.RectangularSize.ID) async throws -> Room
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ extension DatabaseClient.Rooms: TestDependencyKey {
|
|||||||
try await model.validateAndSave(on: database)
|
try await model.validateAndSave(on: database)
|
||||||
return try model.toDTO()
|
return try model.toDTO()
|
||||||
},
|
},
|
||||||
|
createMany: { rooms in
|
||||||
|
try await rooms.asyncMap { request in
|
||||||
|
let model = try request.toModel()
|
||||||
|
try await model.validateAndSave(on: database)
|
||||||
|
return try model.toDTO()
|
||||||
|
}
|
||||||
|
},
|
||||||
delete: { id in
|
delete: { id in
|
||||||
guard let model = try await RoomModel.find(id, on: database) else {
|
guard let model = try await RoomModel.find(id, on: database) else {
|
||||||
throw NotFoundError()
|
throw NotFoundError()
|
||||||
|
|||||||
41
Sources/DatabaseClient/Internal/Sequence+asyncMap.swift
Normal file
41
Sources/DatabaseClient/Internal/Sequence+asyncMap.swift
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Sequence {
|
||||||
|
|
||||||
|
// Taken from: https://forums.swift.org/t/are-there-any-kind-of-asyncmap-method-for-a-normal-sequence/77354/7
|
||||||
|
func asyncMap<Result: Sendable>(
|
||||||
|
_ transform: @escaping @Sendable (Element) async throws -> Result
|
||||||
|
) async rethrows -> [Result] where Element: Sendable {
|
||||||
|
try await withThrowingTaskGroup(of: (Int, Result).self) { group in
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
var iterator = self.makeIterator()
|
||||||
|
var results = [Result?]()
|
||||||
|
results.reserveCapacity(underestimatedCount)
|
||||||
|
|
||||||
|
func submitTask() throws {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
if let element = iterator.next() {
|
||||||
|
results.append(nil)
|
||||||
|
group.addTask { [i] in try await (i, transform(element)) }
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add initial tasks
|
||||||
|
for _ in 0..<ProcessInfo.processInfo.processorCount {
|
||||||
|
try submitTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit more tasks as results complete
|
||||||
|
while let (index, result) = try await group.next() {
|
||||||
|
results[index] = result
|
||||||
|
try submitTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.compactMap { $0 }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
TODO.md
14
TODO.md
@@ -5,14 +5,14 @@
|
|||||||
- [x] Add postgres / mysql support
|
- [x] Add postgres / mysql support
|
||||||
- [ ] Opensource / license ??
|
- [ ] Opensource / license ??
|
||||||
- [ ] Figure out domain to host (currently thinking ductcalc.pro)
|
- [ ] Figure out domain to host (currently thinking ductcalc.pro)
|
||||||
- [ ] Logo / navbar name may have to change if it's not duct-calc.
|
- [ ] Logo / navbar name may have to change if it's not duct-calc.
|
||||||
- [ ] MainPage meta items will have to change also
|
- [ ] MainPage meta items will have to change also
|
||||||
- [ ] Add ability for either sensible or total load while specifying a room load.
|
- [ ] Add ability for either sensible or total load while specifying a room load.
|
||||||
- CoolCalc current version specifies the sensible cooling for a room break down,
|
- CoolCalc current version specifies the sensible cooling for a room break down,
|
||||||
and currently we require the total load and calculate sensible based on project
|
and currently we require the total load and calculate sensible based on project
|
||||||
shr.
|
shr.
|
||||||
- [ ] Add ability to associate room load / airflow with another room.
|
- [ ] Add ability to associate room load / airflow with another room.
|
||||||
- [ ] Trunk size form, room / register selection is wonky when labels are long.
|
- [ ] Trunk size form, room / register selection is wonky when labels are long.
|
||||||
- They will overlap each other making it difficult to read / decipher which checkbox belongs
|
- They will overlap each other making it difficult to read / decipher which checkbox belongs
|
||||||
to which label.
|
to which label.
|
||||||
- [ ] Add select all rooms for trunks, useful for sizing main supply or return trunks.
|
- [ ] Add select all rooms for trunks, useful for sizing main supply or return trunks.
|
||||||
|
|||||||
@@ -43,6 +43,22 @@ struct RoomTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
func createMany() async throws {
|
||||||
|
try await withTestUserAndProject { _, project in
|
||||||
|
@Dependency(\.database.rooms) var rooms
|
||||||
|
|
||||||
|
let created = try await rooms.createMany([
|
||||||
|
.init(projectID: project.id, name: "Test 1", heatingLoad: 1234, coolingTotal: 1234),
|
||||||
|
.init(projectID: project.id, name: "Test 2", heatingLoad: 1234, coolingTotal: 1234),
|
||||||
|
])
|
||||||
|
|
||||||
|
#expect(created.count == 2)
|
||||||
|
#expect(created[0].name == "Test 1")
|
||||||
|
#expect(created[1].name == "Test 2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
func notFound() async throws {
|
func notFound() async throws {
|
||||||
try await withDatabase {
|
try await withDatabase {
|
||||||
@@ -128,61 +144,4 @@ struct RoomTests {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test(
|
|
||||||
// arguments: [
|
|
||||||
// Room.Update(
|
|
||||||
// name: "",
|
|
||||||
// heatingLoad: 12345,
|
|
||||||
// coolingTotal: 12344,
|
|
||||||
// coolingSensible: nil,
|
|
||||||
// registerCount: 1
|
|
||||||
// ),
|
|
||||||
// Room.Update(
|
|
||||||
// name: "Test",
|
|
||||||
// heatingLoad: -12345,
|
|
||||||
// coolingTotal: 12344,
|
|
||||||
// coolingSensible: nil,
|
|
||||||
// registerCount: 1
|
|
||||||
// ),
|
|
||||||
// Room.Update(
|
|
||||||
// name: "Test",
|
|
||||||
// heatingLoad: 12345,
|
|
||||||
// coolingTotal: -12344,
|
|
||||||
// coolingSensible: nil,
|
|
||||||
// registerCount: 1
|
|
||||||
// ),
|
|
||||||
// Room.Update(
|
|
||||||
// name: "Test",
|
|
||||||
// heatingLoad: 12345,
|
|
||||||
// coolingTotal: 12344,
|
|
||||||
// coolingSensible: -123,
|
|
||||||
// registerCount: 1
|
|
||||||
// ),
|
|
||||||
// Room.Update(
|
|
||||||
// name: "Test",
|
|
||||||
// heatingLoad: 12345,
|
|
||||||
// coolingTotal: 12344,
|
|
||||||
// coolingSensible: nil,
|
|
||||||
// registerCount: -1
|
|
||||||
// ),
|
|
||||||
// Room.Update(
|
|
||||||
// name: "",
|
|
||||||
// heatingLoad: -12345,
|
|
||||||
// coolingTotal: -12344,
|
|
||||||
// coolingSensible: -1,
|
|
||||||
// registerCount: -1
|
|
||||||
// ),
|
|
||||||
// ]
|
|
||||||
// )
|
|
||||||
// func updateValidations(room: Room.Update) throws {
|
|
||||||
// #expect(throws: (any Error).self) {
|
|
||||||
// // do {
|
|
||||||
// try room.validate()
|
|
||||||
// // } catch {
|
|
||||||
// // print("\(error)")
|
|
||||||
// // throw error
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user