Skip to content

Instantly share code, notes, and snippets.

@jubishop
Last active December 24, 2024 17:20
Show Gist options
  • Save jubishop/cb0032b1c1ad2728369363d1395ddd92 to your computer and use it in GitHub Desktop.
Save jubishop/cb0032b1c1ad2728369363d1395ddd92 to your computer and use it in GitHub Desktop.
queue management
// MARK: - Queue Management
func dequeue(_ episodeID: Int64) async throws {
try await appDB.db.write { db in
guard let oldPosition = try _fetchOldPosition(db, for: episodeID) else {
return
}
try _moveInQueue(db, episodeID: episodeID, from: oldPosition, to: Int.max)
try Episode.filter(id: episodeID)
.updateAll(db, queueColumn.set(to: nil))
}
}
func insertToQueue(_ episodeID: Int64, at newPosition: Int) async throws {
try await appDB.db.write { db in
try _insertToQueue(db, episodeID: episodeID, at: newPosition)
}
}
func appendToQueue(_ episodeID: Int64) async throws {
try await appDB.db.write { db in
let newPosition =
(try Episode
.select(max(queueColumn), as: Int.self)
.fetchOne(db) ?? 0) + 1
try _insertToQueue(db, episodeID: episodeID, at: newPosition)
}
}
//MARK: - Private Queue Helpers
private let queueColumn = Column("queueOrder")
private func _fetchOldPosition(_ db: Database, for episodeID: Int64) throws
-> Int?
{
precondition(
db.isInsideTransaction,
"fetchOldPosition method requires a transaction"
)
return
try Episode
.filter(id: episodeID)
.select(queueColumn, as: Int.self)
.fetchOne(db)
}
private func _insertToQueue(
_ db: Database,
episodeID: Int64,
at newPosition: Int
) throws {
precondition(
db.isInsideTransaction,
"insertToQueue method requires a transaction"
)
let oldPosition = try _fetchOldPosition(db, for: episodeID) ?? Int.max
let computedNewPosition =
newPosition > oldPosition ? newPosition - 1 : newPosition
try _moveInQueue(
db,
episodeID: episodeID,
from: oldPosition,
to: computedNewPosition
)
try Episode
.filter(id: episodeID)
.updateAll(db, queueColumn.set(to: computedNewPosition))
}
private func _moveInQueue(
_ db: Database,
episodeID: Int64,
from oldPosition: Int,
to newPosition: Int
) throws {
guard newPosition != oldPosition else { return }
precondition(
db.isInsideTransaction,
"moveInQueue method requires a transaction"
)
if newPosition > oldPosition {
try Episode.filter(
queueColumn > oldPosition && queueColumn <= newPosition
)
.updateAll(db, queueColumn.set(to: queueColumn - 1))
} else {
try Episode.filter(
queueColumn >= newPosition && queueColumn < oldPosition
)
.updateAll(db, queueColumn.set(to: queueColumn + 1))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment