Fix service concurrency isolation warnings

This commit is contained in:
John Burwell 2026-05-29 07:24:11 -05:00
parent 2df126ebe2
commit 64f75e73df
5 changed files with 49 additions and 47 deletions

View File

@ -7,7 +7,7 @@
import Foundation
enum MinecraftContentType: String, CaseIterable, Hashable, Sendable, Codable {
nonisolated enum MinecraftContentType: String, CaseIterable, Hashable, Sendable, Codable {
case world = "World"
case behaviorPack = "Behavior Pack"
case resourcePack = "Resource Pack"
@ -56,13 +56,13 @@ enum MinecraftContentType: String, CaseIterable, Hashable, Sendable, Codable {
}
}
enum PackSource: String, Hashable, Sendable, Codable {
nonisolated enum PackSource: String, Hashable, Sendable, Codable {
case referencedByWorld
case embeddedInWorld
case foundInCollection
}
struct ContentPackReference: Identifiable, Hashable, Sendable, Codable {
nonisolated struct ContentPackReference: Identifiable, Hashable, Sendable, Codable {
let id: String
let name: String
let type: MinecraftContentType
@ -93,7 +93,7 @@ struct ContentPackReference: Identifiable, Hashable, Sendable, Codable {
}
}
struct WorldMetadata: Hashable, Sendable, Codable {
nonisolated struct WorldMetadata: Hashable, Sendable, Codable {
var gameMode: String?
var difficulty: String?
var seed: String?
@ -113,11 +113,11 @@ struct WorldMetadata: Hashable, Sendable, Codable {
var networkVersion: String?
}
struct PackMetadataDetails: Hashable, Sendable, Codable {
nonisolated struct PackMetadataDetails: Hashable, Sendable, Codable {
var minimumEngineVersion: String?
}
struct MinecraftContentItem: Identifiable, Hashable, Sendable, Codable {
nonisolated struct MinecraftContentItem: Identifiable, Hashable, Sendable, Codable {
let id: URL
let folderURL: URL
let folderName: String

View File

@ -7,7 +7,7 @@
import Foundation
struct ConnectedDevice: Identifiable, Hashable, Sendable, Codable {
nonisolated struct ConnectedDevice: Identifiable, Hashable, Sendable, Codable {
let udid: String
var name: String
var productType: String?
@ -18,19 +18,19 @@ struct ConnectedDevice: Identifiable, Hashable, Sendable, Codable {
var id: String { udid }
}
enum DeviceConnection: String, Hashable, Sendable, Codable {
nonisolated enum DeviceConnection: String, Hashable, Sendable, Codable {
case usb
case network
}
enum DeviceTrustState: String, Hashable, Sendable, Codable {
nonisolated enum DeviceTrustState: String, Hashable, Sendable, Codable {
case unavailable
case locked
case untrusted
case trusted
}
struct DeviceAppContainer: Identifiable, Hashable, Sendable, Codable {
nonisolated struct DeviceAppContainer: Identifiable, Hashable, Sendable, Codable {
let deviceUDID: String
let appID: String
var appName: String
@ -42,12 +42,12 @@ struct DeviceAppContainer: Identifiable, Hashable, Sendable, Codable {
}
}
enum DeviceContainerAccessMode: String, Hashable, Sendable, Codable {
nonisolated enum DeviceContainerAccessMode: String, Hashable, Sendable, Codable {
case documents
case container
}
enum MinecraftSourceOrigin: Hashable, Sendable, Codable {
nonisolated enum MinecraftSourceOrigin: Hashable, Sendable, Codable {
case localFolder(bookmarkData: Data?)
case connectedDevice(device: ConnectedDevice, container: DeviceAppContainer)
@ -79,7 +79,7 @@ enum MinecraftSourceOrigin: Hashable, Sendable, Codable {
}
}
enum MinecraftSourceKind: String, Hashable, Sendable, Codable {
nonisolated enum MinecraftSourceKind: String, Hashable, Sendable, Codable {
case localFolder
case connectedDevice
}

View File

@ -9,7 +9,7 @@ import Foundation
typealias SourceAccessorIdentifier = String
enum SourceAvailability: String, Hashable, Sendable, Codable {
nonisolated enum SourceAvailability: String, Hashable, Sendable, Codable {
case unknown
case available
case disconnected
@ -17,18 +17,18 @@ enum SourceAvailability: String, Hashable, Sendable, Codable {
case unavailable
}
enum SourceRefreshStrategy: String, Hashable, Sendable, Codable {
nonisolated enum SourceRefreshStrategy: String, Hashable, Sendable, Codable {
case eagerFullScan
case staged
}
struct SourceAccessDescriptor: Hashable, Sendable, Codable {
nonisolated struct SourceAccessDescriptor: Hashable, Sendable, Codable {
var accessorIdentifier: SourceAccessorIdentifier
var kind: MinecraftSourceKind
var refreshStrategy: SourceRefreshStrategy
}
struct SourceRecord: Identifiable, Hashable, Sendable, Codable {
nonisolated struct SourceRecord: Identifiable, Hashable, Sendable, Codable {
let id: URL
var displayName: String
var rootURL: URL

View File

@ -39,7 +39,7 @@ enum SourceScanExecutor {
let previousSource = source
let performanceContext = SourceScanPolicy.performanceContext(for: source)
await host.updateSource(sourceID) { source in
host.updateSource(sourceID) { source in
source.isScanning = true
source.scanError = nil
source.scanDiagnostic = nil
@ -51,11 +51,11 @@ enum SourceScanExecutor {
source.sizeLoadedCount = 0
}
await host.updateSource(sourceID) { source in
host.updateSource(sourceID) { source in
source.accessDescriptor = sourceAccessMethod.accessDescriptor(for: source)
}
let currentAvailability = await sourceAccessMethod.availability(for: source)
await host.updateSource(sourceID) { source in
host.updateSource(sourceID) { source in
source.availability = currentAvailability
}
@ -67,7 +67,7 @@ enum SourceScanExecutor {
}
}
await host.updateSource(sourceID) { source in
host.updateSource(sourceID) { source in
source.availability = .available
source.scanStatus = SourceScanPolicy.scanningLibraryStatus(for: source, mode: mode)
}
@ -86,7 +86,9 @@ enum SourceScanExecutor {
let enrichedItem = await sourceAccessMethod.enrich(item, for: source)
if let snapshot = await index.applyEnrichedItem(enrichedItem) {
await host.applySnapshot(snapshot, to: sourceID)
await MainActor.run {
host.applySnapshot(snapshot, to: sourceID)
}
}
}
}
@ -143,7 +145,7 @@ enum SourceScanExecutor {
itemForIndex,
discoveredCount: discoveredCount
) {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
if itemForIndex.id == item.id, itemForIndex.metadataLoaded == false {
await enrichmentQueue.enqueue(item)
@ -170,13 +172,13 @@ enum SourceScanExecutor {
cachedItem,
discoveredCount: discoveredCount
) {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
}
}
}
await host.logScanStage(
host.logScanStage(
"Discovery",
elapsed: Date().timeIntervalSince(discoveryStartTime),
context: performanceContext,
@ -184,7 +186,7 @@ enum SourceScanExecutor {
)
if let snapshot = await index.markDiscoveryFinished() {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
await enrichmentQueue.finish()
let enrichmentStartTime = Date()
@ -193,7 +195,7 @@ enum SourceScanExecutor {
await workerTask.value
}
await host.logScanStage(
host.logScanStage(
"Enrichment",
elapsed: Date().timeIntervalSince(enrichmentStartTime),
context: performanceContext,
@ -201,9 +203,9 @@ enum SourceScanExecutor {
)
if let snapshot = await index.markMetadataFinished() {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
await host.persistSourceIfAvailable(withID: sourceID)
host.persistSourceIfAvailable(withID: sourceID)
let previewStageStartTime = Date()
let previewSeedItems = await index.currentItems()
@ -213,11 +215,11 @@ enum SourceScanExecutor {
)
for previewItem in previewItems {
if let snapshot = await index.applyPreviewItem(previewItem) {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
}
await host.logScanStage(
host.logScanStage(
"Previews",
elapsed: Date().timeIntervalSince(previewStageStartTime),
context: performanceContext,
@ -225,9 +227,9 @@ enum SourceScanExecutor {
)
if let snapshot = await index.markPreviewsFinished() {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
await host.persistSourceIfAvailable(withID: sourceID)
host.persistSourceIfAvailable(withID: sourceID)
if source.origin.kind == .connectedDevice {
try await finishConnectedDeviceScan(
@ -271,7 +273,7 @@ enum SourceScanExecutor {
await sizeWorkerTask.value
}
await host.logScanStage(
host.logScanStage(
"Size",
elapsed: Date().timeIntervalSince(sizeStageStartTime),
context: performanceContext,
@ -291,7 +293,7 @@ enum SourceScanExecutor {
minimumVisibleScanDuration: minimumVisibleScanDuration
)
} catch {
await host.updateSource(sourceID) { source in
host.updateSource(sourceID) { source in
if SourceScanRecovery.shouldPreservePartialResults(currentSource: source, previousSource: previousSource) {
source.scanStatus = source.indexedItemCount == 0
? previousSource.scanStatus
@ -320,7 +322,7 @@ enum SourceScanExecutor {
source.scanProgress = nil
source.isScanning = false
}
await host.persistSourceIfAvailable(withID: sourceID)
host.persistSourceIfAvailable(withID: sourceID)
}
}
@ -345,11 +347,11 @@ enum SourceScanExecutor {
)
for sizedItem in sizedItems {
if let snapshot = await index.applySizedItem(sizedItem) {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
}
await host.logScanStage(
host.logScanStage(
"Size",
elapsed: Date().timeIntervalSince(sizeStageStartTime),
context: performanceContext,
@ -390,24 +392,24 @@ enum SourceScanExecutor {
}
if let snapshot = await index.finishScan() {
await host.applySnapshot(snapshot, to: sourceID)
host.applySnapshot(snapshot, to: sourceID)
}
await host.updateSource(sourceID) { source in
host.updateSource(sourceID) { source in
if source.origin.kind == .localFolder {
source.snapshot = SourceScanPolicy.buildSnapshot(for: source, scanRootURL: scanContextURL)
} else {
source.snapshot = nil
}
}
await host.persistSourceIfAvailable(withID: sourceID)
await host.logScanStage(
host.persistSourceIfAvailable(withID: sourceID)
host.logScanStage(
"Total",
elapsed: Date().timeIntervalSince(scanStartTime),
context: performanceContext,
itemCount: discoveredCount
)
if let completedSource = await host.source(withID: sourceID) {
if let completedSource = host.source(withID: sourceID) {
await notificationService.notifyScanCompleted(
for: completedSource,
duration: Date().timeIntervalSince(scanStartTime)

View File

@ -8,7 +8,7 @@
import Foundation
import zlib
struct ZipArchiveEntry: Sendable, Hashable {
nonisolated struct ZipArchiveEntry: Sendable, Hashable {
let path: String
let compressionMethod: UInt16
let compressedSize: UInt32
@ -17,7 +17,7 @@ struct ZipArchiveEntry: Sendable, Hashable {
let isDirectory: Bool
}
enum ZipArchiveReaderError: LocalizedError {
nonisolated enum ZipArchiveReaderError: LocalizedError {
case invalidArchive
case unsupportedCompressionMethod(UInt16)
case unsupportedFeatures(String)
@ -40,7 +40,7 @@ enum ZipArchiveReaderError: LocalizedError {
}
}
struct ZipArchiveReader {
nonisolated struct ZipArchiveReader {
private let data: Data
let entries: [ZipArchiveEntry]
@ -241,7 +241,7 @@ struct ZipArchiveReader {
}
}
private extension Data {
private nonisolated extension Data {
func readUInt16LE(at offset: Int) -> UInt16 {
return self.withUnsafeBytes { bytes in
let base = bytes.baseAddress!.advanced(by: offset)