This commit is contained in:
Kevin Jahns 2015-12-01 19:27:14 +01:00
parent 8d14a9cbba
commit 3a55ca4f21
10 changed files with 81 additions and 40 deletions

View File

@ -1,7 +1,7 @@
/* @flow */ /* @flow */
type UserId = string type UserId = string
type Id = [UserId, number] type Id = [UserId, number|string]
/* /*
type Struct = { type Struct = {
@ -11,6 +11,7 @@ type Struct = {
target?: Id, target?: Id,
struct: 'Insert' | 'Delete' struct: 'Insert' | 'Delete'
}*/ }*/
type Struct = Insertion | Deletion type Struct = Insertion | Deletion
type Operation = Struct type Operation = Struct
@ -31,6 +32,19 @@ type Deletion = {
struct: 'Delete' struct: 'Delete'
} }
type MapStruct = {
id: Id,
type: TypeNames,
map: any
}
type ListStruct = {
id: Id,
type: TypeNames,
start: Id,
end: Id
}
type MessageSyncStep1 = { type MessageSyncStep1 = {
type: 'sync step 1', type: 'sync step 1',

View File

@ -14,6 +14,8 @@ type YConfig = {
root: Object root: Object
} }
type TypeName = 'array' | 'map' | 'text'
declare var YConcurrency_TestingMode : boolean declare var YConcurrency_TestingMode : boolean
type Transaction<A> = Generator<any, A, any> type Transaction<A> = Generator<any, A, any>

2
dist

@ -1 +1 @@
Subproject commit b471c91d1d70b1d9e31ba81664d8fab4aff414a2 Subproject commit 434432a742088e4f53aee0230353c18b5e621211

View File

@ -31,7 +31,9 @@ module.exports = function (gulp, helperOptions) {
} }
if (options.includeRuntime) { if (options.includeRuntime) {
files.dist = ['node_modules/regenerator/runtime.js', files.dist] files.distEs5 = ['node_modules/regenerator/runtime.js', files.dist]
} else {
files.distEs5 = [files.dist]
} }
gulp.task('dist:es5', function () { gulp.task('dist:es5', function () {
@ -39,14 +41,14 @@ module.exports = function (gulp, helperOptions) {
presets: ['es2015'] presets: ['es2015']
} }
return (browserify({ return (browserify({
entries: files.dist, entries: files.distEs5,
debug: true debug: true
}).transform('babelify', babelOptions) }).transform('babelify', babelOptions)
.bundle() .bundle()
.pipe(source(options.targetName)) .pipe(source(options.targetName))
.pipe(buffer()) .pipe(buffer())
.pipe($.sourcemaps.init({loadMaps: true})) .pipe($.sourcemaps.init({loadMaps: true}))
.pipe($.uglify()) .pipe($.if(!options.debug, $.uglify()))
.pipe($.sourcemaps.write('.')) .pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./dist/'))) .pipe(gulp.dest('./dist/')))
}) })

View File

@ -59,9 +59,9 @@ require('./gulpfile.helper.js')(gulp, {
] ]
}) })
gulp.task('dev:examples', ['updateSubmodule', 'watch:dist'], function () { gulp.task('dev:examples', ['watch:dist'], function () {
// watch all distfiles and copy them to bower_components // watch all distfiles and copy them to bower_components
var distfiles = ['./dist/*.js', './dist/*.js.map', '../y-*/dist/*.js', '../y-*/dist/*.js.map'] var distfiles = ['./dist/*.{js,es6}', './dist/*.{js,es6}.map', '../y-*/dist/*.{js,es6}', '../y-*/dist/*.{js,es6}.map']
gulp.src(distfiles) gulp.src(distfiles)
.pipe($.watch(distfiles)) .pipe($.watch(distfiles))
.pipe($.rename(function (path) { .pipe($.rename(function (path) {

View File

@ -186,8 +186,8 @@ module.exports = function (Y /* :any */) {
} }
} }
getNextOpId () { getNextOpId () {
if (this._temporaryUserIdGenerator != null) { if (this._nextUserId != null) {
return this._temporaryUserIdGenerator() return this._nextUserId
} else if (this.userId == null) { } else if (this.userId == null) {
throw new Error('OperationStore not yet initialized!') throw new Error('OperationStore not yet initialized!')
} else { } else {
@ -390,7 +390,7 @@ module.exports = function (Y /* :any */) {
} }
} }
requestTransaction (makeGen/* :any */, callImmediately) { requestTransaction (makeGen/* :any */, callImmediately) {
if (callImmediately) { if (true || callImmediately) { // TODO: decide whether this is ok or not..
this.waitingTransactions.push(makeGen) this.waitingTransactions.push(makeGen)
if (!this.transactionInProgress) { if (!this.transactionInProgress) {
this.transactionInProgress = true this.transactionInProgress = true

View File

@ -85,7 +85,7 @@ function * applyTransactions (relAmount, numberOfTransactions, objects, users, t
var r = Math.random() var r = Math.random()
if (r >= 0.5) { if (r >= 0.5) {
// 50% chance to flush // 50% chance to flush
Y.utils.globalRoom.flushOne() // flushes for some user.. (not necessarily 0) yield Y.utils.globalRoom.flushOne() // flushes for some user.. (not necessarily 0)
} else if (r >= 0.05) { } else if (r >= 0.05) {
// 45% chance to create operation // 45% chance to create operation
randomTransaction(getRandom(objects)) randomTransaction(getRandom(objects))
@ -245,6 +245,9 @@ g.createUsers = async(function * createUsers (self, numberOfUsers, database) {
connector: { connector: {
name: 'Test', name: 'Test',
debug: false debug: false
},
share: {
root: 'Map'
} }
})) }))
} }

View File

@ -91,7 +91,7 @@ module.exports = function (Y/* :any */) {
var sid = JSON.stringify(id) var sid = JSON.stringify(id)
var t = this.store.initializedTypes[sid] var t = this.store.initializedTypes[sid]
if (t == null) { if (t == null) {
var op = yield* this.getOperation(id) var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)
if (op != null) { if (op != null) {
t = yield* Y[op.type].initType.call(this, this.store, op) t = yield* Y[op.type].initType.call(this, this.store, op)
this.store.initializedTypes[sid] = t this.store.initializedTypes[sid] = t
@ -398,7 +398,7 @@ module.exports = function (Y/* :any */) {
if (o.parent != null) { if (o.parent != null) {
// remove gc'd op from parent, if it exists // remove gc'd op from parent, if it exists
var parent = yield* this.getOperation(o.parent) var parent /* MapOperation */ = yield* this.getOperation(o.parent)
var setParent = false // whether to save parent to the os var setParent = false // whether to save parent to the os
if (o.parentSub != null) { if (o.parentSub != null) {
if (Y.utils.compareIds(parent.map[o.parentSub], o.id)) { if (Y.utils.compareIds(parent.map[o.parentSub], o.id)) {
@ -558,8 +558,23 @@ module.exports = function (Y/* :any */) {
}) })
} }
} }
* getOperation (id) { * getOperation (id/* :any */)/* :Transaction<any> */ {
return yield* this.os.find(id) var o = yield* this.os.find(id)
if (o != null || id[0] != '_') {
return o
} else {
// need to generate this operation
if (this.store._nextUserId == null) {
var typename= id[1].split('_')[0]
this.store._nextUserId = id
yield* Y[typename].createType.call(this)
delete this.store._nextUserId
return yield* this.os.find(id)
} else {
// Can only generate one operation at a time
return null
}
}
} }
* removeOperation (id) { * removeOperation (id) {
yield* this.os.delete(id) yield* this.os.delete(id)

View File

@ -3,7 +3,7 @@
'use strict' 'use strict'
var Y = require('../SpecHelper.js') var Y = require('../SpecHelper.js')
var numberOfYMapTests = 500 var numberOfYMapTests = 50
var repeatMapTeasts = 1 var repeatMapTeasts = 1
for (let database of databases) { for (let database of databases) {
@ -12,10 +12,10 @@ for (let database of databases) {
beforeEach(async(function * (done) { beforeEach(async(function * (done) {
yield createUsers(this, 5, database) yield createUsers(this, 5, database)
y1 = this.users[0].root y1 = this.users[0].share.root
y2 = this.users[1].root y2 = this.users[1].share.root
y3 = this.users[2].root y3 = this.users[2].share.root
y4 = this.users[3].root y4 = this.users[3].share.root
flushAll = Y.utils.globalRoom.flushAll flushAll = Y.utils.globalRoom.flushAll
done() done()
})) }))
@ -30,7 +30,7 @@ for (let database of databases) {
expect(y1.get('stuff')).toEqual('stuffy') expect(y1.get('stuff')).toEqual('stuffy')
yield flushAll() yield flushAll()
for (var key in this.users) { for (var key in this.users) {
var u = this.users[key].root var u = this.users[key].share.root
expect(u.get('stuff')).toEqual('stuffy') expect(u.get('stuff')).toEqual('stuffy')
} }
done() done()
@ -56,7 +56,7 @@ for (let database of databases) {
yield flushAll() yield flushAll()
for (var key in this.users) { for (var key in this.users) {
var r = this.users[key].root var r = this.users[key].share.root
expect(r.get('stuff')).toEqual('stuffy') expect(r.get('stuff')).toEqual('stuffy')
} }
done() done()
@ -69,7 +69,7 @@ for (let database of databases) {
yield flushAll() yield flushAll()
for (var key in this.users) { for (var key in this.users) {
var u = this.users[key] var u = this.users[key]
expect(u.root.get('stuff')).toEqual('c0') expect(u.share.root.get('stuff')).toEqual('c0')
} }
done() done()
})) }))
@ -82,7 +82,7 @@ for (let database of databases) {
for (var key in this.users) { for (var key in this.users) {
var u = this.users[key] var u = this.users[key]
expect(u.root.get('stuff')).toBeUndefined() expect(u.share.root.get('stuff')).toBeUndefined()
} }
done() done()
})) }))
@ -96,7 +96,7 @@ for (let database of databases) {
for (var key in this.users) { for (var key in this.users) {
var u = this.users[key] var u = this.users[key]
expect(u.root.get('stuff')).toEqual('c0') expect(u.share.root.get('stuff')).toEqual('c0')
} }
done() done()
})) }))
@ -116,7 +116,7 @@ for (let database of databases) {
for (var key in this.users) { for (var key in this.users) {
var u = this.users[key] var u = this.users[key]
expect(u.root.get('stuff')).toBeUndefined() expect(u.share.root.get('stuff')).toBeUndefined()
} }
done() done()
})) }))
@ -199,7 +199,7 @@ for (let database of databases) {
var promises = [] var promises = []
for (var u = 0; u < this.users.length; u++) { for (var u = 0; u < this.users.length; u++) {
promises.push(this.users[u].root.get('Map')) promises.push(this.users[u].share.root.get('Map'))
} }
this.maps = yield Promise.all(promises) this.maps = yield Promise.all(promises)
done() done()

View File

@ -22,6 +22,10 @@ Y.extend = function (name, value) {
Y.requestModules = requestModules Y.requestModules = requestModules
function requestModules (modules) { function requestModules (modules) {
// determine if this module was compiled for es5 or es6 (y.js vs. y.es6)
// if Insert.execute is a Function, then it isnt a generator..
// then load the es5(.js) files..
var extention = Y.Struct.Insert.execute.constructor === Function ? '.js' : '.es6'
var promises = [] var promises = []
for (var i = 0; i < modules.length; i++) { for (var i = 0; i < modules.length; i++) {
var modulename = 'y-' + modules[i].toLowerCase() var modulename = 'y-' + modules[i].toLowerCase()
@ -33,7 +37,7 @@ function requestModules (modules) {
// module does not exist // module does not exist
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
var imported = document.createElement('script') var imported = document.createElement('script')
imported.src = Y.sourceDir + '/' + modulename + '/' + modulename + '.js' imported.src = Y.sourceDir + '/' + modulename + '/' + modulename + extention
document.head.appendChild(imported) document.head.appendChild(imported)
let requireModule = {} let requireModule = {}
@ -69,26 +73,28 @@ type DbOptions = MemoryOptions | IndexedDBOptions
type WebRTCOptions = { type WebRTCOptions = {
name: 'webrtc', name: 'webrtc',
room: string room: string
} }
type WebsocketsClientOptions = { type WebsocketsClientOptions = {
name: 'websockets-client', name: 'websockets-client',
room: string room: string
} }
type ConnectionOptions = WebRTCOptions | WebsocketsClientOptions type ConnectionOptions = WebRTCOptions | WebsocketsClientOptions
type TypesOptions = Array<'array'|'map'|'text'>
type YOptions = { type YOptions = {
connector: ConnectionOptions, connector: ConnectionOptions,
db: DbOptions, db: DbOptions,
types: TypesOptions, types: Array<TypeName>,
sourceDir: string sourceDir: string,
share: {[key: string]: TypeName}
} }
*/ */
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ { function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
opts.types = opts.types != null ? opts.types : [] opts.types = opts.types != null ? opts.types : []
var modules = [opts.db.name, opts.connector.name].concat(opts.types) var modules = [opts.db.name, opts.connector.name].concat(opts.types)
for (var name in opts.share) {
modules.push(opts.share[name])
}
Y.sourceDir = opts.sourceDir Y.sourceDir = opts.sourceDir
return Y.requestModules(modules).then(function () { return Y.requestModules(modules).then(function () {
return new Promise(function (resolve) { return new Promise(function (resolve) {
@ -105,19 +111,18 @@ class YConfig {
/* :: /* ::
db: Y.AbstractDatabase; db: Y.AbstractDatabase;
connector: Y.AbstractConnector; connector: Y.AbstractConnector;
share: {[key: string]: any};
*/ */
constructor (opts, callback) { constructor (opts, callback) {
this.db = new Y[opts.db.name](this, opts.db) this.db = new Y[opts.db.name](this, opts.db)
this.connector = new Y[opts.connector.name](this, opts.connector) this.connector = new Y[opts.connector.name](this, opts.connector)
var share = {}
this.share = share
this.db.requestTransaction(function * requestTransaction () { this.db.requestTransaction(function * requestTransaction () {
// create initial Map type // create shared object
this.store._temporaryUserIdGenerator = function () { for (var propertyname in opts.share) {
return ['_', 0] share[propertyname] = yield* this.getType(['_', opts.share[propertyname] + '_' + propertyname])
} }
var typeid = yield* Y.Map.createType.call(this)
var type = yield* this.getType(typeid)
this.store.y.root = type
this.store._temporaryUserIdGenerator = null
setTimeout(callback, 0) setTimeout(callback, 0)
}) })
} }