foam-framework
Version:
MVC metaprogramming framework
137 lines (123 loc) • 3.84 kB
JavaScript
/*
* @license
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CLASS({
name: 'ParitionDAO',
package: 'foam.core.dao',
extends: 'AbstractDAO',
requires: [
'foam.core.dao.OrderedCollectorSink',
'foam.core.dao.CollectorSink'
],
properties: [
{
name: 'partitions',
type: 'Array[DAO]',
mode: "read-only",
required: true
}
],
methods: {
init: function() {
this.SUPER();
for ( var i = 0; i < this.partitions.length; i++) {
var part = this.partitions[i];
var self = this;
part.listen({
put: function(value) {
self.notify_("put", [value]);
},
remove: function(value) {
self.notify_("remove", [value]);
}
});
}
},
getPartition_: function(value) {
return this.partitions[Math.abs(value.hashCode()) % this.partitions.length];
},
put: function(value, sink) {
this.getPartition_(value).put(value, sink);
},
remove: function(obj, sink) {
if (obj.id) {
this.getPartition_(obj).remove(obj, sink);
} else {
var self = this;
this.find(obj, { put: function(obj) { self.remove(obj, sink); }, error: sink && sink.error });
}
},
find: function(key, sink) {
// Assumes no data redundancy
for (var i = 0; i < this.partitions.length; i++) {
this.partitions[i].find(key, sink);
}
},
select: function(sink, options) {
sink = sink || [].sink;
var myoptions = {};
var originalsink = sink;
options = options || {};
if ( 'limit' in options ) {
myoptions.limit = options.limit + (options.skip || 0),
myoptions.skip = 0;
}
myoptions.order = options.order;
myoptions.query = options.query;
var pending = this.partitions.length;
var fc = this.createFlowControl_();
var future = afuture();
if ( sink.model_ && sink.reduceI ) {
var mysink = sink;
} else {
if ( options.order ) {
mysink = this.OrderedCollectorSink.create({ comparator: options.order });
} else {
mysink = this.CollectorSink.create({});
}
if ( 'limit' in options ) sink = limitedSink(options.limit, sink);
if ( options.skip ) sink = skipSink(options.skip, sink);
mysink.eof = function() {
for (var i = 0; i < this.storage.length; i++) {
if ( fc.stopped ) break;
if ( fc.errorEvt ) {
sink.error && sink.error(fc.errorEvt);
future.set(sink, fc.errorEvt);
break;
}
sink.put(this.storage[i], null, fc);
}
};
}
var sinks = new Array(this.partitions.length);
for ( var i = 0; i < this.partitions.length; i++ ) {
sinks[i] = mysink.deepClone();
sinks[i].eof = function() {
mysink.reduceI(this);
pending--;
if (pending <= 0) {
mysink.eof && mysink.eof();
future.set(originalsink);
}
};
}
for ( var i = 0; i < this.partitions.length; i++ ) {
this.partitions[i].select(sinks[i], myoptions);
}
return future.get;
}
}
});