Created
April 13, 2016 15:20
-
-
Save blairio/8d959a22ef089bb7ebc1547a27110931 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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