NSMigrationManager.migrateStore with NSPersistentHistoryTrackingKey

I am implementing a custom migration, and facing an issue while implementing a WAL checkpointing.

Here is the code for WAL checkpointing

func forceWALCheckpointingForStore(at storeURL: URL, model: NSManagedObjectModel) throws {
	let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)

	let options = [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
	let store = try persistentStoreCoordinator.addPersistentStore(type: .sqlite, at: storeURL, options: options)
	try persistentStoreCoordinator.remove(store)
}

When the coordinator tries to add the store I am getting the following error

fault: Store opened without NSPersistentHistoryTrackingKey but previously had been opened with NSPersistentHistoryTrackingKey - Forcing into Read Only mode store

My questions are

  1. Is it really necessary to force WAL checkpointing before migration? I am expecting NSMigrationManager to handle it internally. I am assuming this because the migrateStore function asks for the sourceType where I am passing StoreType.sqlite
  2. If checkpointing is required, then how do I address the original issue

Note:

  1. Since my app supports macOS 13, I am not able to use the newly introduced Staged migrations.
  2. There is similar question on Stackoverflow that remains unanswered. https://stackoverflow.com/q/69131577/1311902

I don't think you need to explicitly checkpoint the store. The Core Data migration process should handle that for you – If it doesn't, I'd see that a framework bug.

Regarding the error, did you try to set up options in the following way:

let options = [
	NSSQLitePragmasOption: ["journal_mode": "DELETE"],
	NSPersistentHistoryTrackingKey: true as NSNumber
]

Alternatively, you can use NSPersistentContainer to do the same thing:

let container = NSPersistentContainer(name: "<your container name>")
let storeURL = ...
let storeDescription = NSPersistentStoreDescription(url: storeURL)

// Turn off lightweight migration options if you would prevent auto migration.
// Core Data will then return error if the model version is incompatibile.
//
storeDescription.shouldMigrateStoreAutomatically = false
storeDescription.shouldInferMappingModelAutomatically = false
storeDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)

container.persistentStoreDescriptions = [storeDescription]
container.loadPersistentStores { (storeDescription, error) in
    ...
}

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

How can I confirm this behavior when migrating using NSMigrationManager?

I don't think you need to explicitly checkpoint the store. The Core Data migration process should handle that for you – If it doesn't, I'd see that a framework bug

When I enable com.apple.CoreData.MigrationDebug the lightweight migration logs the WAL checkpointing, however, when using NSMigrationManager no such log appears. When I tried inserting 1000 objects, all of them get inserted into the sqlite file. Nothing gets inserted in WAL file. Is the behavior different for NSPersistentCloudKitContainer?


Regarding the error, did you try to set up options in the following way:

Yes, this works. However, if the NSMigrationManager handles this then should be avoided, right?

The code path of lightweight migration, which does migration in place, is different from the one of running NSMigrationManager, and so I am not too surprised that the logs are different. If you can provide the logs generated by running NSMigrationManager for me to compare, I will be able to confirm. I'll be very surprised if NSMigrationManager doesn't checkpoint the data though.

I don't see any way that can force Core Data to write to the -wal file. I think if you set up a Core Data stack with multiple persistent store coordinators and write a bigger data set simultaneously, you will more likely see data being witten to the -wal file. I don't expect the behavior being different for NSPersistentCloudKitContainer.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

These are the logs when migration happens from NSMigrationManager

NSMigrationManager.migrateStore with NSPersistentHistoryTrackingKey
 
 
Q