mirror of
https://github.com/status-im/realm-js.git
synced 2025-02-22 11:18:15 +00:00
Add shouldCompactOnLaunch option to configuration (#1209)
* Adding shouldCompactOnLaunch option to configuration * Adding Realm.compact()
This commit is contained in:
parent
0c557fcfe5
commit
bd28c05936
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,3 +1,16 @@
|
||||
X.Y.Z Release notes
|
||||
=============================================================
|
||||
### Breaking changes
|
||||
* None
|
||||
|
||||
### Enhancements
|
||||
* Added `shouldCompactOnLaunch` to configuration (#507).
|
||||
* Added `Realm.compact()` for manually compacting Realm files.
|
||||
|
||||
### Bug fixes
|
||||
* None
|
||||
|
||||
|
||||
1.10.3 Release notes (2017-8-16)
|
||||
=============================================================
|
||||
### Breaking changes
|
||||
|
@ -182,6 +182,24 @@ class Realm {
|
||||
* @param {function()} callback
|
||||
*/
|
||||
write(callback) {}
|
||||
|
||||
/**
|
||||
* Replaces all string columns in this Realm with a string enumeration column and compacts the
|
||||
* database file.
|
||||
*
|
||||
* Cannot be called from a write transaction.
|
||||
*
|
||||
* Compaction will not occur if other `Realm` instances exist.
|
||||
*
|
||||
* While compaction is in progress, attempts by other threads or processes to open the database will
|
||||
* wait.
|
||||
*
|
||||
* Be warned that resource requirements for compaction is proportional to the amount of live data in
|
||||
* the database. Compaction works by writing the database contents to a temporary database file and
|
||||
* then replacing the database with the temporary one.
|
||||
* @returns {true} if compaction succeeds.
|
||||
*/
|
||||
compact() {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,6 +231,13 @@ Realm.defaultPath;
|
||||
* This function takes two arguments:
|
||||
* - `oldRealm` - The Realm before migration is performed.
|
||||
* - `newRealm` - The Realm that uses the latest `schema`, which should be modified as necessary.
|
||||
* @property {callback(number, number)} [shouldCompactOnLaunch] - The function called when opening
|
||||
* a Realm for the first time during the life of a process to determine if it should be compacted
|
||||
* before being returned to the user. The function takes two arguments:
|
||||
* - `totalSize` - The total file size (data + free space)
|
||||
* - `unusedSize` - The total bytes used by data in the file.
|
||||
* It returns `true` to indicate that an attempt to compact the file should be made. The compaction
|
||||
* will be skipped if another process is accessing it.
|
||||
* @property {string} [path={@link Realm.defaultPath}] - The path to the file where the
|
||||
* Realm database should be stored.
|
||||
* @property {boolean} [readOnly=false] - Specifies if this Realm should be opened as read-only.
|
||||
|
@ -132,6 +132,7 @@ util.createMethods(Realm.prototype, objectTypes.REALM, [
|
||||
'delete',
|
||||
'deleteAll',
|
||||
'write',
|
||||
'compact',
|
||||
], true);
|
||||
|
||||
const Sync = {
|
||||
|
6
lib/index.d.ts
vendored
6
lib/index.d.ts
vendored
@ -77,6 +77,7 @@ declare namespace Realm {
|
||||
interface Configuration {
|
||||
encryptionKey?: ArrayBuffer | ArrayBufferView | Int8Array;
|
||||
migration?: (oldRealm: Realm, newRealm: Realm) => void;
|
||||
shouldCompactOnLaunch?: (totalBytes: number, usedBytes: number) => boolean;
|
||||
path?: string;
|
||||
readOnly?: boolean;
|
||||
schema?: ObjectClass[] | ObjectSchema[];
|
||||
@ -452,6 +453,11 @@ declare class Realm {
|
||||
* @returns void
|
||||
*/
|
||||
write(callback: () => void): void;
|
||||
|
||||
/**
|
||||
* @returns boolean
|
||||
*/
|
||||
compact(): boolean;
|
||||
}
|
||||
|
||||
declare module 'realm' {
|
||||
|
@ -176,6 +176,8 @@ public:
|
||||
static void remove_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void remove_all_listeners(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void close(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void compact(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
||||
|
||||
// properties
|
||||
static void get_empty(ContextType, ObjectType, ReturnValue &);
|
||||
@ -223,6 +225,7 @@ public:
|
||||
{"removeListener", wrap<remove_listener>},
|
||||
{"removeAllListeners", wrap<remove_all_listeners>},
|
||||
{"close", wrap<close>},
|
||||
{"compact", wrap<compact>},
|
||||
};
|
||||
|
||||
PropertyMap<T> const properties = {
|
||||
@ -390,6 +393,28 @@ void RealmClass<T>::constructor(ContextType ctx, ObjectType this_object, size_t
|
||||
config.schema_version = 0;
|
||||
}
|
||||
|
||||
static const String compact_on_launch_string = "shouldCompactOnLaunch";
|
||||
ValueType compact_value = Object::get_property(ctx, object, compact_on_launch_string);
|
||||
if (!Value::is_undefined(ctx, compact_value)) {
|
||||
if (config.schema_mode == SchemaMode::ReadOnly) {
|
||||
throw std::invalid_argument("Cannot set 'shouldCompactOnLaunch' when 'readOnly' is set.");
|
||||
}
|
||||
if (config.sync_config) {
|
||||
throw std::invalid_argument("Cannot set 'shouldCompactOnLaunch' when 'sync' is set.");
|
||||
}
|
||||
|
||||
FunctionType should_compact_on_launch_function = Value::validated_to_function(ctx, compact_value, "shouldCompactOnLaunch");
|
||||
config.should_compact_on_launch_function = [=](uint64_t total_bytes, uint64_t unused_bytes) {
|
||||
ValueType arguments[2] = {
|
||||
Value::from_number(ctx, total_bytes),
|
||||
Value::from_number(ctx, unused_bytes)
|
||||
};
|
||||
|
||||
ValueType should_compact = Function<T>::callback(ctx, should_compact_on_launch_function, this_object, 2, arguments);
|
||||
return Value::to_boolean(ctx, should_compact);
|
||||
};
|
||||
}
|
||||
|
||||
static const String migration_string = "migration";
|
||||
ValueType migration_value = Object::get_property(ctx, object, migration_string);
|
||||
if (!Value::is_undefined(ctx, migration_value)) {
|
||||
@ -836,5 +861,17 @@ void RealmClass<T>::close(ContextType ctx, FunctionType, ObjectType this_object,
|
||||
realm->close();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RealmClass<T>::compact(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 0);
|
||||
|
||||
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
|
||||
if (realm->is_in_transaction()) {
|
||||
throw std::runtime_error("Cannot compact a Realm within a transaction.");
|
||||
}
|
||||
|
||||
return_value.set(realm->compact());
|
||||
}
|
||||
|
||||
} // js
|
||||
} // realm
|
||||
|
@ -943,5 +943,61 @@ module.exports = {
|
||||
|
||||
realm.write(() => realm.delete(realm.objects('PersonObject')));
|
||||
TestCase.assertTrue(realm.empty);
|
||||
},
|
||||
|
||||
testCompact: function() {
|
||||
var wasCalled = false;
|
||||
const count = 1000;
|
||||
// create compactable Realm
|
||||
const realm1 = new Realm({schema: [schemas.StringOnly]});
|
||||
realm1.write(() => {
|
||||
realm1.create('StringOnlyObject', { stringCol: 'A' });
|
||||
for (var i = 0; i < count; i++) {
|
||||
realm1.create('StringOnlyObject', { stringCol: 'ABCDEFG' });
|
||||
}
|
||||
realm1.create('StringOnlyObject', { stringCol: 'B' });
|
||||
});
|
||||
realm1.close();
|
||||
|
||||
// open Realm and see if it is compacted
|
||||
var shouldCompact = function(totalBytes, usedBytes) {
|
||||
wasCalled = true;
|
||||
const fiveHundredKB = 500*1024;
|
||||
return (totalBytes > fiveHundredKB) && (usedBytes / totalBytes) < 0.2;
|
||||
};
|
||||
const realm2 = new Realm({schema: [schemas.StringOnly], shouldCompactOnLaunch: shouldCompact});
|
||||
TestCase.assertTrue(wasCalled);
|
||||
TestCase.assertEqual(realm2.objects('StringOnlyObject').length, count + 2);
|
||||
// we don't check if the file is smaller as we assume that Object Store does it
|
||||
realm2.close();
|
||||
},
|
||||
|
||||
testManualCompact: function() {
|
||||
const realm1 = new Realm({schema: [schemas.StringOnly]});
|
||||
realm1.write(() => {
|
||||
realm1.create('StringOnlyObject', { stringCol: 'A' });
|
||||
});
|
||||
TestCase.assertTrue(realm1.compact());
|
||||
realm1.close();
|
||||
|
||||
const realm2 = new Realm({schema: [schemas.StringOnly]});
|
||||
TestCase.assertEqual(realm2.objects('StringOnlyObject').length, 1);
|
||||
realm2.close();
|
||||
},
|
||||
|
||||
testManualCompactInWrite: function() {
|
||||
const realm = new Realm({schema: [schemas.StringOnly]});
|
||||
realm.write(() => {
|
||||
TestCase.assertThrows(() => {
|
||||
realm.compact();
|
||||
});
|
||||
});
|
||||
TestCase.assertTrue(realm.empty);
|
||||
},
|
||||
|
||||
testManualCompactMultipleInstances: function() {
|
||||
const realm1 = new Realm({schema: [schemas.StringOnly]});
|
||||
const realm2 = new Realm({schema: [schemas.StringOnly]});
|
||||
TestCase.assertThrows(realm1.compact());
|
||||
}
|
||||
};
|
||||
|
@ -126,6 +126,13 @@ exports.StringPrimary = {
|
||||
}
|
||||
};
|
||||
|
||||
exports.StringOnly = {
|
||||
name: 'StringOnlyObject',
|
||||
properties: {
|
||||
stringCol: 'string',
|
||||
}
|
||||
};
|
||||
|
||||
exports.AllTypes = {
|
||||
name: 'AllTypesObject',
|
||||
primaryKey: 'primaryCol',
|
||||
|
Loading…
x
Reference in New Issue
Block a user