Skip to content

Commit

Permalink
Serialize promises.
Browse files Browse the repository at this point in the history
  • Loading branch information
NAME authored and NAME committed Dec 7, 2016
1 parent 6c6cb9c commit 1751499
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 90 deletions.
32 changes: 0 additions & 32 deletions .idea/runConfigurations/Relay.xml

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions sub/apollo/src/client/view/detail.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ const DetailQuery = gql`
}
`;


// TODO(burdon): New Synax: http://dev.apollodata.com/react/fragments.html
// ${CommentsPage.fragments.comment} instead of createFragment/query.fragments option below.

const mapStateToProps = (state, ownProps) => {
let { minder } = state;

Expand Down
1 change: 1 addition & 0 deletions sub/apollo/src/client/view/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class Layout extends React.Component {

{/*
* Debug sidebar.
* TODO(burdon): Redux vs custom panel.
*/}
<div className="app-debug">
<Monitor/>
Expand Down
3 changes: 3 additions & 0 deletions sub/apollo/src/server/db/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import { ItemStore } from 'minder-core';
*/
export class FirebaseStore {

// TODO(burdon): Namespace (prod, qa, dev-rich, dev-adam).
// TODO(burdon): Type-based namespace.

// TODO(burdon): Move to sub/data.

static sanitizeKey(key) {
Expand Down
73 changes: 44 additions & 29 deletions sub/apollo/src/server/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ const port = process.env['VIRTUAL_PORT'] || 3000;

//
// Express.
// TODO(burdon): Use injector pattern (esp for async startup).
//

// TODO(burdon): Use injector pattern (esp for async startup).
let promises = [];

const app = express();

const server = http.Server(app);
Expand Down Expand Up @@ -97,31 +99,40 @@ _.each(require('./testing/test.json'), (items, type) => {
database.upsertItems(context, _.map(items, (item) => ({ type, ...item })));
});

// Create team.
database.queryItems({}, {}, { type: 'User' }).then(users => {
console.log('USERS', JSON.stringify(users));

database.getItem(context, 'Group', 'minderlabs').then(item => {
item.members = _.map(users, user => user.id);
database.upsertItem(context, item);
});
});

// TODO(burdon): Webhook?
const testData = true;
if (testData) {
new Randomizer(database, context)
.generate('Contact', 20)
.generate('Place', 10)
.generate('Task', 15, {
owner: {
type: 'User', likelihood: 1.0
},
assignee: {
type: 'User', likelihood: 0.5
}
});
}
// Create test data.
promises.push(database.queryItems({}, {}, { type: 'User' })
.then(users => {
console.log('USERS', JSON.stringify(users));

// Create group.
return database.getItem(context, 'Group', 'minderlabs')

.then(item => {
item.members = _.map(users, user => user.id);
database.upsertItem(context, item);
});
})

// TODO(burdon): Webhook to create random data?
.then(() => {
const testData = true;
if (testData) {
let randomizer = new Randomizer(database, context);

return Promise.all([
randomizer.generate('Contact', 20),
randomizer.generate('Place', 10),
randomizer.generate('Task', 15, {
owner: {
type: 'User', likelihood: 1.0
},
assignee: {
type: 'User', likelihood: 0.5
}
})
]);
}
}));


//
Expand Down Expand Up @@ -240,7 +251,11 @@ app.use(function(req, res) {
// Start-up.
//

server.listen(port, host, () => {
let addr = server.address();
console.log(`### RUNNING[${env}] http://${addr.address}:${addr.port} ###`);
Promise.all(promises).then(() => {
console.log('STARTING...');

server.listen(port, host, () => {
let addr = server.address();
console.log(`### RUNNING[${env}] http://${addr.address}:${addr.port} ###`);
});
});
File renamed without changes.
23 changes: 23 additions & 0 deletions sub/core/src/util/type.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,27 @@ export class TypeUtil {

return array;
}

/**
* Iterates the collection sequentially calling the async function for each.
*
* @param collection Data to iterate.
* @param func Returns a value or promise.
* @return {Promise}
*/
static iterateWithPromises(collection, func) {

let p = Promise.resolve();

_.each(collection, (...args) => {

p = p.then(() => {

return Promise.resolve(func.apply(null, args));
});
});

// Resolve after each item in the sequence resolves.
return p;
}
}
56 changes: 56 additions & 0 deletions sub/core/src/util/type.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// Copyright 2016 Minder Labs.
//

'use strict';

import { TypeUtil } from './type';

describe('Types:', () => {

it ('zzz', (done) => {

function f(i) {
return new Promise((resolve, reject) => {
console.log('A', i);
resolve();
}).then(() => {
console.log('B', i);
});
}

Promise.all([f(1), f(2)])
.then(() => {
console.log('C');
done();
});

});


it('Iterator of promises.', (done) => {

let values = [];

// Async function.
let f = (i) => {
values.push(i);

return Promise.resolve(i);
};

TypeUtil.iterateWithPromises(_.times(5), (i) => {
return f(i);

}).then((value) => {

// Last value.
expect(value).to.equal(4);

// Test done sequentially.
expect(values.length).to.equal(5);

done();
});
});
});
72 changes: 48 additions & 24 deletions sub/graphql/src/testing/randomizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import _ from 'lodash';

import { Chance } from 'chance';

import { TypeUtil } from 'minder-core';

/**
* Randomizer
*/
Expand Down Expand Up @@ -47,14 +49,42 @@ export class Randomizer {
this._database = database;
this._context = context;
this._chance = new Chance(seed);
this._cache = new Map();
}

/**
* Query the database or return a cached value.
* @param filter
* @return {Promise}
*/
queryCache(filter) {
let key = JSON.stringify(filter);
let result = this._cache.get(key);
if (result) {
return Promise.resolve(result);
} else {
// TODO(burdon): Generalize for more general database use?
return this._database.queryItems(this._context, {}, filter).then(values => {
this._cache.set(key, values);
return values;
});
}
}

/**
*
* @param type
* @param n
* @param fields
* @return Promise
*/
generate(type, n, fields={}) {
console.log('GENERATE[%s]: %d', type, n);

let promises = [];
let items = [];

let items = _.times(n, (i) => {
// Create values.
return TypeUtil.iterateWithPromises(_.times(n), (i) => {

// Generate item.
let item = {
Expand All @@ -64,30 +94,24 @@ export class Randomizer {
...Randomizer.generators[type](this._chance)
};

// Generate fields.
_.each(fields, (spec, field) => {
if (this._chance.bool({ likelihood: spec.likelihood * 100 })) {

// TODO(burdon): Cache queries.
promises.push(this._database.queryItems(this._context, {}, { type: spec.type }).then(values => {
if (values.length) {
let index = this._chance.integer({ min: 0, max: values.length - 1 });
let value = values[index];
item[field] = value.id;
}
}));
}
});
items.push(item);

return item;
});
// Iterate fields.
return TypeUtil.iterateWithPromises(fields, (spec, field) => {

// TODO(burdon): Is there a better way to batch multiple queries?
// Wait for everything to complete.
Promise.all(promises).then(() => {
this._database.upsertItems(this._context, items);
});
// Get items for generator's filter.
return this.queryCache({ type: spec.type }).then(values => {
if (values.length) {
let index = this._chance.integer({ min: 0, max: values.length - 1 });
let value = values[index];
item[field] = value.id;
}
});
});
}).then(() => {

return this;
// Insert vector of items.
return this._database.upsertItems(this._context, items);
});
}
}
13 changes: 10 additions & 3 deletions sub/graphql/src/util/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,23 @@ export const graphqlLogger = (options={ pretty: false }) => {
// TODO(burdon): Not efficient intercepting write.
let json = JSON.parse(data);
switch (res.statusCode) {
case 200:
case 200: {
if (options.pretty) {
console.log(PRETTY_RES, moment().format(TS), stringify(json));
} else {
console.log('### RES ### %s', stringify(json));
}

break;
}

default:
console.error('Network error: %d', res.statusCode);
default: {
// TODO(burdon): Get error?
console.error('### ERR[%d] ###', res.statusCode);
_.each(json.errors, (err) => {
console.log('> %s', err.message);
});
}
}

return originalWrite.call(res, data);
Expand Down

0 comments on commit 1751499

Please sign in to comment.