diff --git a/README.md b/README.md index 8681b70..9e2eb7a 100644 --- a/README.md +++ b/README.md @@ -550,6 +550,14 @@ function changeProjectDatabase(dbName, dbUser, dbPassword) { ``` +## Eventually Consistent + +Following the CouchDB consistency model, we have introduced `ENV.emberPouch.eventuallyConsistent`. This feature is on by default. So if you want the old behavior you'll have to disable this flag. + +`findRecord` now returns a long running Promise if the record is not found. It only rejects the promise if a deletion of the record is found. Otherwise this promise will wait for eternity to resolve. +This makes sure that belongsTo relations that have been loaded in an unexpected order will still resolve correctly. This makes sure that ember-data does not set the belongsTo to null if the Pouch replicate would have loaded the related object later on. (This only works for async belongsTo, sync versions will need this to be implemented in relational-pouch) + + ## Installation * `git clone` this repository diff --git a/addon/adapters/pouch.js b/addon/adapters/pouch.js index 38e44f1..09a93d6 100644 --- a/addon/adapters/pouch.js +++ b/addon/adapters/pouch.js @@ -5,7 +5,8 @@ import { pluralize } from 'ember-inflector'; import { extractDeleteRecord, - shouldSaveRelationship + shouldSaveRelationship, + configFlagDisabled } from '../utils'; const { @@ -418,7 +419,10 @@ export default DS.RESTAdapter.extend({ } } - return this._eventuallyConsistent(recordTypeName, id); + if (configFlagDisabled(this, 'eventuallyConsistent')) + throw "Document of type '" + recordTypeName + "' with id '" + id + "' not found."; + else + return this._eventuallyConsistent(recordTypeName, id); }); }, diff --git a/addon/utils.js b/addon/utils.js index da4118f..0a0f404 100644 --- a/addon/utils.js +++ b/addon/utils.js @@ -13,9 +13,25 @@ export function shouldSaveRelationship(container, relationship) { if (relationship.kind === 'belongsTo') return true; //TODO: save default locally? probably on container? - let config = Ember.getOwner(container).resolveRegistration('config:environment'); - let saveDefault = config['emberPouch'] && config['emberPouch']['saveHasMany']; - //default is false if not specified + let saveDefault = configFlagEnabled('saveHasMany');//default is false if not specified return saveDefault; } + +export function configFlagDisabled(container, key) { + //default is on + let config = Ember.getOwner(container).resolveRegistration('config:environment'); + let result = config['emberPouch'] && + (typeof config['emberPouch'][key] !== 'undefined') && + !config['emberPouch'][key]; + + return result; +} + +export function configFlagEnabled(container, key) { + //default is off + let config = Ember.getOwner(container).resolveRegistration('config:environment'); + let result = config['emberPouch'] && config['emberPouch'][key]; + + return result; +} diff --git a/tests/integration/adapters/pouch-basics-test.js b/tests/integration/adapters/pouch-basics-test.js index fc924c5..9f6415b 100644 --- a/tests/integration/adapters/pouch-basics-test.js +++ b/tests/integration/adapters/pouch-basics-test.js @@ -437,6 +437,28 @@ test('delete cascade null', function (assert) { 'deleted soup should have cascaded to a null value for the belongsTo'); }).finally(done); }); + +module('not eventually consistent', { beforeEach: function() { + config.emberPouch.eventuallyConsistent = false; + }, + afterEach: function() { + config.emberPouch.eventuallyConsistent = true; + } + }, function() { + test('not found', function (assert) { + assert.expect(2); + assert.ok(config.emberPouch.eventuallyConsistent == false, 'eventuallyConsistent is false'); + let done = assert.async(); + + Ember.RSVP.Promise.resolve().then(() => this.store().findRecord('food-item', 'non-existent') + .then(() => assert.ok(false)) + .catch(() => { + assert.ok(true, 'item is not found'); + done(); + })); + }); +}); + }; let syncAsync = function() {