Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Modules/Sources/Storage/CoreData/CoreDataIterativeMigrator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ final class CoreDataIterativeMigrator {
// Find the current model used by the store.
let sourceModel = try model(for: sourceMetadata)

// Check if we should nuke the DB entirely based on the oldest supported data model.
// We will attempt to either move the merchant to the latest model version, or perform an iterative migration
// The persistent store coordinator will automatically create a fresh store with the current model as needed.
if shouldDestroyPersistentStore(for: sourceModel) {
do {
try persistentStoreCoordinator.destroyPersistentStore(at: sourceStoreURL, ofType: storeType, options: nil)
DDLogInfo("[CoreDataIterativeMigrator] Database at \(sourceStoreURL) destroyed successfully.")
} catch {
DDLogError("[CoreDataIterativeMigrator] Database destruction failed. Error: \(error). Falling back to iterative migration.")
}
}

// Get the steps to perform the migration.
let steps = try MigrationStep.steps(using: modelsInventory, source: sourceModel, target: targetModel)
guard !steps.isEmpty else {
Expand Down Expand Up @@ -176,4 +188,18 @@ private extension CoreDataIterativeMigrator {
.appendingPathComponent("migration_\(UUID().uuidString)")
.appendingPathExtension("sqlite")
}

func shouldDestroyPersistentStore(for sourceModel: NSManagedObjectModel) -> Bool {
guard let sourceVersion = CoreDataMigratorUtils.findSourceVersion(for: sourceModel, in: modelsInventory) else {
// If the model is not found in inventory it's from a deleted model version
// The database can be destroyed for a fresh start
DDLogInfo("Source model not found in available model versions. Will destroy database for fresh start.")
return true
}

// Model found in inventory, so it's a supported version. Use iterative migration
DDLogInfo("Source model \(sourceVersion.name) found in available versions. Will use iterative migration.")
return false
}

}
2 changes: 1 addition & 1 deletion Modules/Sources/Storage/CoreData/CoreDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public final class CoreDataManager: StorageManagerType {
}

/// Migrates the current persistent store to the latest data model if needed.
/// - Returns: an array of debug messages for logging. Please feel free to remove when #2371 is resolved.
/// - Returns: an array of debug messages for logging.
private static func migrateDataModelIfNecessary(using coordinator: NSPersistentStoreCoordinator,
storeURL: URL,
modelsInventory: ManagedObjectModelsInventory) -> [String] {
Expand Down
19 changes: 19 additions & 0 deletions Modules/Sources/Storage/CoreData/CoreDataMigratorUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import CoreData

struct CoreDataMigratorUtils {
/// Finds the ModelVersion that corresponds to the given NSManagedObjectModel
static func findSourceVersion(for sourceModel: NSManagedObjectModel,
in modelsInventory: ManagedObjectModelsInventory) -> ManagedObjectModelsInventory.ModelVersion? {
do {
let allModels = try modelsInventory.models(for: modelsInventory.versions)
for (index, model) in allModels.enumerated() {
if model.isEqual(sourceModel) {
return modelsInventory.versions[index]
}
}
Comment on lines +8 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Trying to ensure that it can return a deleted version. When I printed out modelsInventory.versions when launching the app in CoreDataManager.migrateDataModelIfNecessary, the versions are 30+; and modelsInventory.models(for:) maps the versions. Can a deleted version be returned, and thus be matched to a source model?

If it's not possible, I think the code can be simplified by not having to compare with the oldest model version constant, since the available models in modelsInventory.versions already imply the oldest version. If it makes sense, shouldDestroyPersistentStore can return true when a model version cannot be found, when this function returns nil.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very good catch, and excellent suggestion. We can just rely on the existence of the model rather than having to check the version, which simplifies the logic and allows us to remove some. Updated here: 6080964

} catch {
DDLogError("[CoreDataMigratorUtils] Error loading models for version detection: \(error)")
}
return nil
}
}
58 changes: 29 additions & 29 deletions Modules/Sources/Storage/Model/MIGRATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,50 +459,50 @@ This file documents changes in the WCiOS Storage data model. Please explain any
- Delete `OrderStats` entity
- Delete `OrderStatsItem` entity

## Model 29 (Release 4.7.0.0)
## Model 29 (Release 4.7.0.0) - Deleted
- @pmusolino 2020-06-29
- Add `siteID` attribute to `ProductTag` entity
- Update `ProductTag`'s `product` relationship to `products`
- Update `Product`'s `tags` relationship with `nullify` as delete rule
- Used mapping model: `WooCommerceModelV28toV29.xcmappingmodel` to remove product tags without `siteID`

## Model 28 (Release 4.5.0.0)
## Model 28 (Release 4.5.0.0) - Deleted
- @jaclync 2020-06-05
- Add `buttonText` attribute to `Product` entity

## Model 27 (Release 3.9.0.1)
## Model 27 (Release 3.9.0.1) - Deleted
- @ecarrion 2020-03-30
- Update `ProductCategory`'s `product` relationship to `products`
- Add `siteID` and `parentID` to `ProductCategory` entity
- Used mapping model: `WooCommerceModelV26toV27.xcmappingmodel` to remove product categories without `siteID`

## Model 26 (Release 3.5.0.0)
## Model 26 (Release 3.5.0.0) - Deleted
- @jaclync 2019-01-14
- Update `Product`'s `images` relationship to be ordered

## Model 25 (Release 3.4.0.0)
## Model 25 (Release 3.4.0.0) - Deleted
- @pmusolino 2019-01-7
- Add `gmtOffset` attribute to `Site` entity

## Model 24 (Release 3.3.0.0)
## Model 24 (Release 3.3.0.0) - Deleted
- @jaclync 2019-12-2
- New `ProductShippingClass` entity
- Add `dateOnSaleStart` attribute to `Product` entity
- Add `dateOnSaleEnd` attribute to `Product` entity
- New `TaxClass` entity

## Model 23 (Release 3.2.0.0)
## Model 23 (Release 3.2.0.0) - Deleted
- @jaclync 2019-11-15
- New `Attribute` entity
- New `ProductVariation` entity
- New `Product.productVariations` relationship

## Model 22 (Release 3.1.0.0)
## Model 22 (Release 3.1.0.0) - Deleted
- @pmusolino 2019-11-4
- New `ShippingLine` entity
- New `Order.shippingLines` relationship

## Model 21 (Release 2.9.0.0)
## Model 21 (Release 2.9.0.0) - Deleted
- @mindgraffiti 2019-10-11
- New `OrderItemTax` entity
- New `OrderItemTaxRefund` entity
Expand All @@ -512,7 +512,7 @@ This file documents changes in the WCiOS Storage data model. Please explain any
- New `Refund` entity
- New `Refund.items` relationship

## Model 20 (Release 2.8.0.0)
## Model 20 (Release 2.8.0.0) - Deleted
- @jaclync 2019-09-17
- New `ProductSearchResults` entity
- New `Product.searchResults` relationship
Expand All @@ -524,7 +524,7 @@ This file documents changes in the WCiOS Storage data model. Please explain any
- New `OrderRefundCondensed` entity
- New `Order.refunds` relationship

## Model 19 (Release 2.6.0.0)
## Model 19 (Release 2.6.0.0) - Deleted
- @ctarda 2019-08-21
- Add `ProductReview` entity

Expand All @@ -534,33 +534,33 @@ This file documents changes in the WCiOS Storage data model. Please explain any
- @jaclync 2019-08-06
- Add `timeRange` attribute to `OrderStatsV4` entity

## Model 18 (Release 2.5.0.0)
## Model 18 (Release 2.5.0.0) - Deleted
- @ctarda 2019-07-30
- Add `OrderCount` entity
- Add `OrderCountItem` entity

## Model 17 (Release 2.3.0.0)
## Model 17 (Release 2.3.0.0) - Deleted
- @ctarda 2019-07-10
- Add `OrderStatsV4` entity
- Add `OrderStatsV4Totals` entity
- Add `OrderStatsV4Interval` entity

## Model 16 (Release 2.0.0.0)
## Model 16 (Release 2.0.0.0) - Deleted
- @mindgraffiti 2019-05-29
- Add `ProductDownload` entity

## Model 15 (Release 1.9.0.0)
## Model 15 (Release 1.9.0.0) - Deleted
- @mindgraffiti 2019-05-03
- Delete `ProductVariation` entity
- Delete `ProductVariationAttribute` entity
- Delete `ProductVariationDimensions` entity
- Delete `ProductVariationImage` entity

## Model 14 (Release 1.8.0.0)
## Model 14 (Release 1.8.0.0) - Deleted
- @astralbodies 2019-04-22
- New `AccountSettings` entity with `tracksOptOut` attribute.

## Model 13 (Release 1.6.0.0)
## Model 13 (Release 1.6.0.0) - Deleted
- @bummytime 2019-03-28
- Added `settingGroupKey` attribute on `SiteSetting` entity

Expand All @@ -570,7 +570,7 @@ This file documents changes in the WCiOS Storage data model. Please explain any
- New `ProductVariationDimensions` entity
- New `ProductVariationImage` entity

## Model 12 (Release 1.5.0.0)
## Model 12 (Release 1.5.0.0) - Deleted
- @bummytime 2019-03-20
- New `Product` entity
- New `ProductDefaultAttribute` entity
Expand All @@ -583,13 +583,13 @@ This file documents changes in the WCiOS Storage data model. Please explain any
- @ctarda 2019-03-14
- Adds `ShipmentTrackingProvider` and `ShipmentTrackingProviderGroup`

## Model 11 (Release 1.4.0.0)
## Model 11 (Release 1.4.0.0) - Deleted

- @mindgraffiti 2019-02-27
- Adds `siteID` and `total` attributes to `OrderStatus`
- Changes `name` and `total` on `OrderStatus` to be optional

## Model 10 (Release 1.3.0.0)
## Model 10 (Release 1.3.0.0) - Deleted
Used mapping model: `WooCommerceModelV9toV10.xcmappingmodel`

- @astralbodies 2019-02-08
Expand All @@ -602,29 +602,29 @@ Used mapping model: `WooCommerceModelV9toV10.xcmappingmodel`
- Changes `status` attribute on `Order` to `statusKey`
- New `OrderStatus` entity

## Model 9 (Release 1.0.0.1)
## Model 9 (Release 1.0.0.1) - Deleted
- @bummytime 2019-01-11
- Added `price` attribute on `OrderItem` entity

Note: the 1.0.0 model 9 never made it to our users so we are not reving the version #.

## Model 9 (Release 1.0.0)
## Model 9 (Release 1.0.0) - Deleted
- @jleandroperez 2018-12-26
- New `Order.exclusiveForSearch` property
- New `OrderSearchResults` entity

## Model 8 (Release 0.13)
## Model 8 (Release 0.13) - Deleted
- @jleandroperez 2018-12-14
- Removed `Site.isJetpackInstalled` attribute.

- @bummytime 2018-12-11
- New `OrderNote.author` attribute

## Model 7
## Model 7 - Deleted
- @bummytime 2018-11-26
- New `Note.deleteInProgress` property

## Model 6
## Model 6 - Deleted
- @jleandroperez 2018-11-15
- New `Note.siteID` property

Expand All @@ -635,26 +635,26 @@ Note: the 1.0.0 model 9 never made it to our users so we are not reving the vers
- Added new attribute: `isJetpackInstalled`, to site entity
- Added new attribute: `plan`, to site entity

## Model 5
## Model 5 - Deleted
- @bummytime 2018-10-26
- Added new entity: `Note`, to encapsulate all things notifications

- @bummytime 2018-10-23
- Added new entity: `SiteSetting`, to encapsulate all of the site settings

## Model 4
## Model 4 - Deleted
- @bummytime 2018-10-09
- Added new entity: `SiteVisitStats`, to encapsulate all of the visitor stats for a given site & granularity
- Added new entity: `SiteVisitStatsItem`, to encapsulate all the visitor stats for a specific period
- Added new entity: `OrderStats`, to encapsulate all of the order stats for a given site & granularity
- Added new entity: `OrderStatsItem`, to encapsulate all the order stats for a specific period

## Model 3
## Model 3 - Deleted
- @bummytime 2018-09-19
- Widened `quantity` attribute on `OrderItem` from Int16 to Int64
- Widened `quantity` attribute on `TopEarnerStatsItem` from Int16 to Int64

## Model 2
## Model 2 - Deleted
- @bummytime 2018-09-05
- Added new entity: `TopEarnerStats`, to encapsulate all of the top earner stats for a given site & granularity
- Added new entity: `TopEarnerStatsItem`, to encapsulate all the top earner stats for a specific product
Loading