Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RLMConfiguration #1584

Closed
alazier opened this issue Mar 9, 2015 · 17 comments · Fixed by #2326
Closed

Add RLMConfiguration #1584

alazier opened this issue Mar 9, 2015 · 17 comments · Fixed by #2326
Assignees

Comments

@alazier
Copy link
Contributor

alazier commented Mar 9, 2015

Encapsulate all global state/config used to configure Realms so that we don't need separate config methods for every parameter.

@jpsim
Copy link
Contributor

jpsim commented Mar 9, 2015

  • Encryption Key
  • Readonly
  • NSFileProtection attributes

Anything else?

@alazier
Copy link
Contributor Author

alazier commented Mar 9, 2015

Should consider supporting:

  • path
  • encryptionKey
  • readonly
  • fileProtection
  • inMemoryIdentifier
  • schemaVersion/migrationBlock
  • schema (for dynamic realm support)

@segiddins
Copy link
Contributor

Maybe also the classes that should be used for that schema?

@bmunkholm
Copy link
Contributor

And let's align this with the Java cousin: realm/realm-java#929

@cmelchior
Copy link
Contributor

The above are pretty much what I intended to add for Java as well, except from FileProtection which is not relevant on Java.

I was also considering adding to other two initialisation methods:

  • deleteRealmBeforeOpening
  • deleteRealmIfMigrationNeeded

Which covers some use cases we have seen pop up fairly often.

@kishikawakatsumi
Copy link
Contributor

How about NSURLIsExcludedFromBackupKey? (to prevent iCloud backup)

https://developer.apple.com/library/ios/qa/qa1719/_index.html

@segiddins
Copy link
Contributor

Below is the Objective-C API I've been sketching out, along with +[RLMRealm realmWithConfiguration].

////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#import <Foundation/Foundation.h>
#import <Realm/RLMRealm.h>

@protocol RLMConfigurator <NSObject>

@property (nonatomic, copy) NSString *path;
@property (nonatomic, copy) NSString *inMemoryIdentifier;
@property (nonatomic, copy) NSData *encryptionKey;
@property (nonatomic)       BOOL    readonly;
@property (nonatomic, copy) NSString *fileProtectionAttributes;

@property (nonatomic)       NSUInteger schemaVersion;
@property (nonatomic, copy) RLMMigrationBlock migrationBlock;

@property (nonatomic)       BOOL deleteBeforeOpening;
@property (nonatomic)       BOOL deleteIfMigrationNeeded;

@end

@interface RLMConfiguration : NSObject<NSCopying>

+ (instancetype)defaultConfiguration;

+ (void)setDefaultConfiguration:(RLMConfiguration *)configuration;

+ (instancetype)configurationWithBlock:(void (^)(id <RLMConfigurator> configurator))block;

@property (nonatomic, copy, readonly) NSString *path;
@property (nonatomic, copy, readonly) NSString *inMemoryIdentifier;
@property (nonatomic, copy, readonly) NSData *encryptionKey;
@property (nonatomic, readonly)       BOOL    readonly;
@property (nonatomic, readonly)       BOOL    dynamic;
@property (nonatomic, copy, readonly) NSString *fileProtectionAttributes;
@property (nonatomic, copy)           id customSchema;

@property (nonatomic, readonly)       NSUInteger schemaVersion;
@property (nonatomic, copy, readonly) RLMMigrationBlock migrationBlock;

@property (nonatomic, readonly)       BOOL deleteBeforeOpening;
@property (nonatomic, readonly)       BOOL deleteIfMigrationNeeded;

@end

@jpsim
Copy link
Contributor

jpsim commented Apr 2, 2015

I'd rather not have deleteBeforeOpening. Just use an in-memory realm at that point.

Same for deleteIfMigrationNeeded, I feel there's a safer, more flexible way to offer similar functionality, either by #1723 or adding the ability to clear a realm during a migration.

Instead of file protection and potentially URL resource value properties, a way to get all realm files for a realm at a specified path might be more flexible. [RLMRealm generatedFilesForRealmsAtPath:].

I can't think of a good way to separate path and inMemoryIdentifier, but having both as settable isn't ideal.

As for the builder pattern, I think it lends itself well to having lots of options, especially if we continue to add some in the future. Good idea.

@segiddins
Copy link
Contributor

After making some implementation progress, I'm not sure this feel like an improvement. In our own tests, what used to be one line to create a realm now requires 3-5 lines

@cmelchior
Copy link
Contributor

A few comments:

deleteBeforeOpening and deleteIfMigrationNeeded are probably coming from the Java API. We havn't yet discussed whether they should be included or not. They are just part of my initial brainstorming. I can see why deleteBeforeOpening could be replaced with in-memory Realms, we just havn't implemented that yet in Java.

deleteIfMigrationNeeded is a lot better and shorter for a lot of use cases where you don't want to bother with migrations. Forcing people to add a migration block and then call a method for this functionality doesn't seem very easy to me.

With regard to code length, I had the same thoughts as @segiddins about the brevity of unit tests. One just has to remember that unit tests are completely different beast than actually app code. In app code you would either set a default configuration or point to a global variabel holding the configuration, as you have very few Realm configurations there, but they are used repeatedly.

Unit tests might have a lot of different configurations, and I found it a lot easier to either setup a default configuration in the unit test setup method or use a Factory class with almost the same API as the old constructors.

@yasirmturk
Copy link

what about cleaning of older schema? dropping not needed tables from other models?

@jpsim
Copy link
Contributor

jpsim commented May 5, 2015

We just had a quick chat (@tgoyne @segiddins @bdash and I) and determined that to avoid multi-process race conditions, we should add a deleteIfMigrationNeeded to RLMConfiguration. /fyi @cmelchior

@segiddins
Copy link
Contributor

(This has been started in seg-config)

@cmelchior
Copy link
Contributor

@segiddins @jpsim @bdash How do you plan to support schemaVersion/MigrationBlock?

Currently on the Java side we have two separate methods for this:

  • RealmConfiguration.schemaVersion(42)
  • RealmConfiguration.migration(new MyCustomMigration())

It might make sense to combine these as having a version above 0 makes very little sense without a migration block at the same time. Something along the lines of

  • RealmConfiguration.schemaVersion(42, new MyMigrationBlock())

Counter to that is deleteIfMigrationNeeded in which case having a migration block doesn't make much sense.

Our current behaviour is this:

  1. If only schemaVersion is set we make a no-op migration behind the scenes that try to upgrade the version number. Schema is validated afterwards and throw an exception if there is mismatch.

  2. If newSchemaVersion > currentSchemaVersion and a migration block is set. This migration will be called when first opening the Realm. We also have a method on the Realm for manually triggering this migration. Useful if you want to upgrade on a background thread: Realm.migrateRealm(RealmConfiguration)

  3. Setting a migration block without a schemaVersion is a no-op, ie. migration code is never called. We might want to log a warning or throw an exception for this.

  4. Setting a newSchemaVersion < currentSchemaVersion will throw an exception when opening the Realm.

  5. Setting newSchemaVersion == currentSchemaVersion and a schema mismatch is detected will throw an exception when opening the Realm.

@drn
Copy link

drn commented Jun 10, 2015

Hey everyone,

I've been lurking for the past few months waiting for a safe way to "delete if migration missing". Looks like the seg-config branch referenced above has gone stale. Are there still plans to add a deleteIfMigrationNeeded option?

Right now, I'm using a TryCatch block bridged from Obj-C (in Swift w/ objc Realm) with a

    NSFileManager.defaultManager().removeItemAtPath(
      RLMRealm.defaultRealmPath(), error: nil
    )

This works most of the time, but I'm getting an occasional

Thanx[84497:2200997] *** Terminating app due to uncaught exception 'RLMException', reason: 'open() failed: No such file or directory'

Anyway, looking forward to hearing of any status updates!

Cheers,
Darren

@yasirmturk
Copy link

we need a proper published guide on this

@ObjSal
Copy link

ObjSal commented Aug 21, 2015

Great job guys! I see these improvements got merged into master, when is it to be released?
I'm very interested in using multiple Realms with different schemas.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants