Skip to content

Instantly share code, notes, and snippets.

@blairio
Created April 13, 2016 15:20
Show Gist options
  • Save blairio/8d959a22ef089bb7ebc1547a27110931 to your computer and use it in GitHub Desktop.
Save blairio/8d959a22ef089bb7ebc1547a27110931 to your computer and use it in GitHub Desktop.
class Storage {
constructor(dbName, remoteDbUrl) {
this.dbName = dbName
this.remoteDbUrl = remoteDbUrl;
}
init() {
this.database = new manager(`http://127.0.0.1:5984/`, this.dbName);
return this.database.createDatabase().then(res => {
if (!res.ok && (res.status !== 412 || res.error !== 'file_exists')) {
throw new Error(`Error connecting to Storage: ${JSON.stringify(res)}, ${JSON.stringify(this)}`);
}
});
};
getAll() {
return this.database.getAllDocuments();
};
get(key) {
return this.database.getDocument(key);
};
startReplication(source, target, createTarget) {
return this.database.replicate(source, target, true, createTarget).then((res) => {
if (!res.session_id) {
throw new Error(JSON.stringify(res));
}
return res.session_id;
});
};
/**
* @returns {Promise} a promise with the event listener that the caller can then subscribe to.
* @throws if the change feed cannot be initialized (eg. last_seq cannot be retrieved from the database)
* For proper use with React Native see https://colinramsay.co.uk/2015/07/04/react-native-eventemitters.html
* Emits two possible events:
* * 'change' with JSON parsed result from change feed as argument
* * 'error' with last error or bad response Errors will be logged automatically to console
* After an error there is delay before listening again with exponential backoff.
*/
getChangesEventEmitter() {
if (!this.changesEventEmitter) {
this.changesEventEmitter = new EventEmitter();
this.changesRetryCount = 0;
return this.database.latestRevision().then(lastRevision => {
this.lastSequence = lastRevision;
this.listenForChange();
return this.changesEventEmitter;
})
} else {
return Promise.resolve(this.changesEventEmitter);
}
};
/**
* Override the default change feed options with new options
* See See Query parameters in http://developer.couchbase.com/documentation/mobile/1.2/develop/references/couchbase-lite/rest-api/database/get-changes/index.html
* @returns void
*/
setChangesFeedOptions(options) {
this.changeFeedOptions = options;
};
getChangesFeedOptions() {
return Object.assign({feed: 'longpoll'}, this.changeFeedOptions || {}, {since: this.lastSequence});
};
listenForChange() {
const params = this.getChangesFeedOptions();
console.log('Listening for changes with', params);
return this.database.getChanges(params).then(res => {
if (typeof(res.last_seq) === 'number') {
this.lastSequence = res.last_seq;
this.changesRetryCount = 0;
this.changesEventEmitter.emit(CHANGE_EVENT_TYPE, res);
} else {
throw new Error(JSON.stringify(res));
}
return this.listenForChange();
}).catch((error) => {
this.changesRetryCount += 1;
console.log('ERROR Listening for changes, RetryCount=', this.changesRetryCount, 'Error=', error);
this.changesEventEmitter.emit(ERROR_EVENT_TYPE, error);
return new Promise((resolve, reject) => {
setTimeout(resolve, this.retryDelay(this.changesRetryCount));
}).then(() => {
return this.listenForChange()
});
})
};
retryDelay(retryCount = 0) {
return (Math.exp(retryCount)) + 15 + (Math.random() * 30 * (retryCount + 1))
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment