This is a change in the code to introduce the entity Cat (no change to Dog):
// struct Dog...classCat:CoreStoreObject,Identifiable{@Field.Stored("identifier",dynamicInitialValue:{UUID()})varid:UUID@Field.Stored("name")varname:String=""}CoreStoreDefaults.dataStack=DataStack(CoreStoreSchema(modelVersion:"V1",entities:[Entity<Dog>("Dog")],versionLock:["Dog":[0x318f24569ce1979d,0xc617bd516e8b8676,0x5d49bce952f15e16,0xe8f2f5c52286f1d3]// Same version lock]),CoreStoreSchema(modelVersion:"V2",entities:[Entity<Dog>("Dog"),Entity<Cat>("Cat")],versionLock:["Dog":[0x318f24569ce1979d,0xc617bd516e8b8676,0x5d49bce952f15e16,0xe8f2f5c52286f1d3],// Same version lock"Cat":[0x303f93c3bcb0c108,0x3ca1f5d4fdc3e42b,0xbcb7e18668333b8e,0x4c26e8e6a7327eb3],]),migrationChain:["V1","V2"])try!CoreStoreDefaults.dataStack.addStorageAndWait(SQLiteStore(fileURL:SQLiteStore().fileURL,localStorageOptions:.allowSynchronousLightweightMigration))
Errors when running
CoreData
DataStack.swift:544 calls coordinator.addPersistentStore which triggers the error to console:
Removing dispatches to the main thread of completion handlers, in storage setup code
Calling addStorage on a background thread
Blocking the main thread with a semaphore until addStorage completes
@ptrkstr commented on GitHub (Jan 5, 2024):
I was able to create a synchronous version of:
```swift
func addStorage<T: LocalStorage>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void) -> Progress?
```
This didn't work with the non-progress function
```swift
func addStorage<T>(_ storage: T, completion: @escaping (SetupResult<T>) -> Void)
```
which caused the following CoreData error:
```
Exception was caught during NSPersistentStoreCoordinator -performBlock: Cannot create an SQL store with a nil URL.
```
You can see the code changes for this here:
- https://github.com/JohnEstropia/CoreStore/compare/develop...ptrkstr:CoreStore:develop?expand=1
Which contains:
- Removing dispatches to the main thread of completion handlers, in storage setup code
- Calling `addStorage` on a background thread
- Blocking the main thread with a semaphore until `addStorage` completes
If by lightweight migration issue you're referring to being able to perform a lightweight migration synchronously, then yes, attached is a video and project (which points to the above branch) demonstrating this.
Given lightweight migration performed synchronously is possible with vanilla CoreData, could it be supported by CoreStore?
@ptrkstr commented on GitHub (Jan 9, 2024):
If by lightweight migration issue you're referring to being able to perform a lightweight migration synchronously, then yes, attached is a video and project (which points to the above branch) demonstrating this.
Given lightweight migration performed synchronously is possible with vanilla CoreData, could it be supported by CoreStore?
[💡CoreStore 2.zip](https://github.com/JohnEstropia/CoreStore/files/13877310/CoreStore.2.zip)
https://github.com/JohnEstropia/CoreStore/assets/11362913/c60508be-13a3-41cf-a5a1-3db8c74657d3
Thanks for creating a demo app! It helped clarify what's going on.
It's been raised before and I just completely forgot about it, so I'm so sorry about the delays.
Core Data actually cannot execute a "lightweight migration" on this model, that is, addPersistentStore() fails on both the async and sync versions of CoreStore's addStorage* methods.
What does succeed is the proceeding "Inferred Migration", where CoreStore's async method initializes an inferred mapping model and calls NSMigrationManager.migrateStore() for you. This is not Apple's advertized "lightweight migration" that requires only the addPersistentStore() call.
Admittedly, I never researched in detail what schema changes this "lightweight migration" does succeed at. I guess at this point I can consider lifting this discrepancy for CoreStore's API consumers and just treat .allowSynchronousLightweightMigration as something like .allowSynchronousInferredMigration instead, but I never supported this from the start because of one reason:
The use of Mapping Models (even inferred) means that there is a possibility that all records will be loaded into memory at some point. If so then this would be significantly slower and memory intensive for a synchronous blocking method. Note that a lot of developers call addStorageAndWait() from the AppDelegate's didLaunchWithOptions or something like your Demo's App.init that blocks the app's launch process and will increase likelihood to get terminated by the OS's watchdog timer
@JohnEstropia commented on GitHub (Jan 11, 2024):
Thanks for creating a demo app! It helped clarify what's going on.
[It's been raised before](https://github.com/JohnEstropia/CoreStore/issues/277#issuecomment-430069780) and I just completely forgot about it, so I'm so sorry about the delays.
Core Data actually cannot execute a **"lightweight migration"** on this model, that is, `addPersistentStore()` fails on both the async and sync versions of CoreStore's `addStorage*` methods.
What does succeed is the proceeding **"Inferred Migration"**, where CoreStore's async method initializes an inferred mapping model and calls `NSMigrationManager.migrateStore()` for you. This is not Apple's advertized **"lightweight migration"** that requires only the `addPersistentStore()` call.
Admittedly, I never researched in detail what schema changes this "lightweight migration" does succeed at. I guess at this point I can consider lifting this discrepancy for CoreStore's API consumers and just treat `.allowSynchronousLightweightMigration` as something like `.allowSynchronousInferredMigration` instead, but I never supported this from the start because of one reason:
- The use of Mapping Models (even inferred) means that there is a possibility that all records will be loaded into memory at some point. If so then this would be significantly slower and memory intensive for a synchronous blocking method. Note that a lot of developers call `addStorageAndWait()` from the AppDelegate's `didLaunchWithOptions` or something like your Demo's `App.init` that blocks the app's launch process and will increase likelihood to get **terminated by the OS's [watchdog timer](https://developer.apple.com/documentation/xcode/addressing-watchdog-terminations)**
Hey @JohnEstropia thanks so much for spending more time explaining this 🙏
I did do a search for this situation and did come across that post but I must have missed that comment.
Your point about memory use in inferred migrations is a good reason to avoid it, I will look into restructuring my application to support async migrations.
what schema changes this "lightweight migration" does succeed at
Perhaps this is the takeaway from this whole issue 😅
Regardless I will close the issue as CoreStore's API does enforce best practises and it may lead to issues if they are modified to support synchronous inferred migration in a simpler way.
Thank you for being an active maintainer @JohnEstropia, I have sent a one-time sponsorship in exchange for the time you have spent responding to me.
@ptrkstr commented on GitHub (Jan 13, 2024):
Hey @JohnEstropia thanks so much for spending more time explaining this 🙏
I did do a search for this situation and did come across that post but I must have missed that comment.
Your point about memory use in inferred migrations is a good reason to avoid it, I will look into restructuring my application to support async migrations.
> what schema changes this "lightweight migration" does succeed at
Perhaps this is the takeaway from this whole issue 😅
Regardless I will close the issue as CoreStore's API does enforce best practises and it may lead to issues if they are modified to support synchronous inferred migration in a simpler way.
Thank you for being an active maintainer @JohnEstropia, I have sent a one-time sponsorship in exchange for the time you have spent responding to me.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @ptrkstr on GitHub (Jan 3, 2024).
Hey @JohnEstropia, thank you for CoreStore ❤️
I am following the Synchronous Lightweight Migration guide from the readme.
My new model has a new entity which is supported by lightweight migration:
This is code that is live (CoreStore 9.2.0):
This is a change in the code to introduce the entity
Cat(no change toDog):Errors when running
CoreData
DataStack.swift:544 calls
coordinator.addPersistentStorewhich triggers the error to console:CoreStore error
Questions
Is this a design decision by CoreStore to not allow synchronous lightweight migration? (my understanding is this is achievable in CoreData directly)
Sample Project
💡CoreStore.zip
@ptrkstr commented on GitHub (Jan 5, 2024):
I was able to create a synchronous version of:
This didn't work with the non-progress function
which caused the following CoreData error:
You can see the code changes for this here:
Which contains:
addStorageon a background threadaddStoragecompletes@JohnEstropia commented on GitHub (Jan 9, 2024):
@ptrkstr Does your update above actually resolve the lightweight migration issue?
@ptrkstr commented on GitHub (Jan 9, 2024):
If by lightweight migration issue you're referring to being able to perform a lightweight migration synchronously, then yes, attached is a video and project (which points to the above branch) demonstrating this.
Given lightweight migration performed synchronously is possible with vanilla CoreData, could it be supported by CoreStore?
💡CoreStore 2.zip
https://github.com/JohnEstropia/CoreStore/assets/11362913/c60508be-13a3-41cf-a5a1-3db8c74657d3
@JohnEstropia commented on GitHub (Jan 11, 2024):
Thanks for creating a demo app! It helped clarify what's going on.
It's been raised before and I just completely forgot about it, so I'm so sorry about the delays.
Core Data actually cannot execute a "lightweight migration" on this model, that is,
addPersistentStore()fails on both the async and sync versions of CoreStore'saddStorage*methods.What does succeed is the proceeding "Inferred Migration", where CoreStore's async method initializes an inferred mapping model and calls
NSMigrationManager.migrateStore()for you. This is not Apple's advertized "lightweight migration" that requires only theaddPersistentStore()call.Admittedly, I never researched in detail what schema changes this "lightweight migration" does succeed at. I guess at this point I can consider lifting this discrepancy for CoreStore's API consumers and just treat
.allowSynchronousLightweightMigrationas something like.allowSynchronousInferredMigrationinstead, but I never supported this from the start because of one reason:addStorageAndWait()from the AppDelegate'sdidLaunchWithOptionsor something like your Demo'sApp.initthat blocks the app's launch process and will increase likelihood to get terminated by the OS's watchdog timer@ptrkstr commented on GitHub (Jan 13, 2024):
Hey @JohnEstropia thanks so much for spending more time explaining this 🙏
I did do a search for this situation and did come across that post but I must have missed that comment.
Your point about memory use in inferred migrations is a good reason to avoid it, I will look into restructuring my application to support async migrations.
Perhaps this is the takeaway from this whole issue 😅
Regardless I will close the issue as CoreStore's API does enforce best practises and it may lead to issues if they are modified to support synchronous inferred migration in a simpler way.
Thank you for being an active maintainer @JohnEstropia, I have sent a one-time sponsorship in exchange for the time you have spent responding to me.