Post

Replies

Boosts

Views

Activity

Reply to `NSPersistentStore` metadata update synchronisation
If you were to dealloc a NSManagedObjectContext before saving it, all changes go away like they never happened, including any updates to the metadata for the store. I'm not sure that's the case. I understand the role of a managed object context as a scratchpad for the store, and that with any NSManagedObjects owned by the context, this is certainly the case. But in the case of store metadata specifically i.e the dictionary that is retrieved and set by NSPersistentStore's metadata(for:)/setMetadata(_:for:) methods – this isn't reflected in the tests I've done. I've experimented with adding a store metadata entry in one context, then calling rollback. If the store metadata was context sensitive you would expect the metadata entry to be now be gone. However, you can then go on to read the store metadata in another context and the pre-rollback changes are still there! The strange part to me is that you have to call save on any context for the store metadata to persist, which I think creates the confusion.
Dec ’20
Reply to `NSPersistentStore` metadata update synchronisation
This is great – thank you. One thing I'm still confused about though is the timing of saving store metadata. Specifically, NSPersistentStore's metadata(for:)/setMetadata(_:for:) method pair. In the docs for the setMetadata(_:for:) method, it states: Important: Setting the metadata for a store does not change the information on disk until the store is actually saved. This is the point that really isn't clear to me. As far as I'm aware, saving a context, is the only way to save a store – and therefore store metadata. But metadata(for:)/setMetadata(_:for:) don't indicate they are context aware – they operate at the PSC/Store level after all. So doesn't that mean that when any context is saved, it will persist changes to the store metadata that could have been made anywhere else? If so, does this not create the possibility that if you have multiple contexts (even if just a background context and a view context), a save on one context may persist changes to your store metadata that were made during a performChanges block of another context? For example, say I have your sequence processing on my background context: Fetch change tokens to send to server Request from Server with change tokens Receive Payload Consume Payload Update change tokens in metadata Write to Disk Notify main thread But, for some reason, at the 'write to disk' stage (no. 6) – we fail. So we rollback the changes on our BG context – and I assume we must now update the store metadata again with our previous change token. Meanwhile however, our user has made an update on the view context and saves – right between points 5-6. If I understand how setMetadata(_:for:) works according to the quoted docs above, that would mean the save on the view context now persists the changes made at no. 5 even though it was made in a performChanges block on our BG context. So, that means that if we happen to crash during the process of the rollback on our failed background update, the store will now contain incorrect metadata. If so, I guess the solution here would to simply create an additional model entity for your metadata and use that instead of NSPersistentStore's metadata(for:)/setMetadata(_:for:) pair – but wanted to make sure I'm not re-inventing the wheel.
Dec ’20
Reply to Cloudkit Request Per Second
Superseding my other answers and at risk of spamming the forum, here's my understanding of how this works: The CloudKit page - https://developer.apple.com/icloud/cloudkit/ seems to split the usage quota into whether you are using the private or public database. Here's where I've got to. Private Database per user quota: As far as I can tell, this is all billed/calculated on a per user basis. As a developer, you will never be billed for usage of a user's private database. Also, If there is a group of users with crazy usage patterns, they shouldn't affect any of your other users quotas – just their own. 10GB Asset Storage (Photos, Videos, etc.) 100MB Data storage (Structured data in the CloudKit key-value store) 2GB Data Transfer (This is unclear, but I'm assuming it's calculated per month.) 40 Requests per second (I'm assuming a user will get throttled if they perform more than 3 requests in a 2 second period.) Public Database all user quota: Whilst Apple does provide an average 'per user' calculation in their calculator on their CloudKit page, I think this actually confuses matters. This is because the 'per user' quota on the public database is an average based on Apple's definition of an active user – someone who has accessed your public database container within the last 16 months – rather than your typical Monthly Active Users (MAUs). This is actually a good thing, as those users that aren't retained bump up the shared allocation for your remaining users – for 16 months after they last used the app! However, now when you create a 'per user' average of the quotas – they look more conservative than they actually are. The truth is that for most apps usage patterns are going to vary wildly between super-engaged contributing users, casual users, and users that have churned never to return again. With this in mind the quotas look pretty good: 1PB (1000TB) Asset Storage (Photos, Videos, etc.) 10TB Database Storage (Structured data in the CloudKit key-value store) 200TB data transfer 400 requests per second. So, to summarise, I'd ignore the per-user average figures for the public database – they're a red herring. Do some calculations for your own app's usage patterns based on Apple's 16-month Active Users definition from the overall quota.
Nov ’20
Reply to CloudKit private database costs
I'm finding this confusing too! The CloudKit page - https://developer.apple.com/icloud/cloudkit/ seems to split the usage quota into whether you are using the private or public database. Here's where I've got to. Private Database per user quota: As far as I can tell, this is all billed/calculated on a per user basis. As a developer, you will never be billed for usage of a user's private database. Also, If there is a group of users with crazy usage patterns, they shouldn't affect any of your other users quotas – just their own. 10GB Asset Storage (Photos, Videos, etc.) 100MB Data storage (Structured data in the CloudKit key-value store) 2GB Data Transfer (This is unclear, but I'm assuming it's calculated per month.) 40 Requests per second (I'm assuming a user will get throttled if they perform more than 3 requests in a 2 second period.) Public Database all user quota: Whilst Apple does provide an average 'per user' calculation in their calculator on their CloudKit page, I think this actually confuses matters. This is because the 'per user' quota on the public database is an average based on Apple's definition of an active user – someone who has accessed your public database container within the last 16 months – rather than your typical Monthly Active Users (MAUs). This is actually a good thing, as those users that aren't retained bump up the shared allocation for your remaining users – for 16 months after they last used the app! However, now when you create a 'per user' average of the quotas – they look more conservative than they actually are. The truth is that for most apps usage patterns are going to vary wildly between super-engaged contributing users, casual users, and users that have churned never to return again. With this in mind the quotas look pretty good: 1PB (1000TB) Asset Storage (Photos, Videos, etc.) 10TB Database Storage (Structured data in the CloudKit key-value store) 200TB data transfer 400 requests per second. So, to summarise, I'd ignore the per-user average figures for the public database – they're a red herring. Do some calculations for your own app's usage patterns based on Apple's 16-month Active Users definition from the overall quota.
Nov ’20
Reply to Cloudkit Request Per Second
Yes, the throttling aspect is my concern here. When you look at the marketing page, the calculator prominently features '4,000,000 active users' and gives the impression that the free (and apparently only) tier can support a high volume app. But when you run the numbers on requests per second, that feels optimistic. I think many developers will be hoping to create a high traffic app, and the thought of it being throttled at the point they manage to generate some traction will give pause for thought. It's certainly making me think twice about CloudKit – which is a shame as it looks really convenient.
Nov ’20
Reply to Cloudkit Request Per Second
It’s not very clear, but the calculator at the CloudKit developer marketing page - https://developer.apple.com/icloud/cloudkit/ appears to explain it as, up to 400k active users, you’re limited to 40 requests per second on the total active user base. That’s further segmented to 10 requests per second per 100k active users. So, say if you have an app where each user makes an average of 10 requests per min (0.167 req. per sec) during use, the max concurrent users you’d be able to support is 60. (limitper100k / 0.167 = 60 ) Is that calculation correct, Apple?
Nov ’20