Add timed cache to user count queries

This commit is contained in:
Berkeley Martinez
2016-04-05 14:45:09 -07:00
parent c57f1b6f9a
commit 06ea132257
3 changed files with 39 additions and 24 deletions

View File

@ -2,40 +2,43 @@ import { Observable } from 'rx';
import dedent from 'dedent';
import moment from 'moment';
import { observeMethod } from '../utils/rx';
import { timeCache, observeMethod } from '../utils/rx';
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
// userCount(where: Object) => Observable[Number]
// getCertCount(userCount: userCount, cert: String) => Observable[Number]
function getCertCount(userCount, cert) {
return userCount({ [cert]: true })
// using This-Bind operator
::timeCache(2, 'hours');
}
export default function about(app) {
const router = app.loopback.Router();
const User = app.models.User;
const userCount$ = observeMethod(User, 'count');
const userCount = observeMethod(User, 'count');
const frontEndCount$ = getCertCount(userCount, 'isFrontEndCert');
const dataVisCount$ = getCertCount(userCount, 'isDataVisCert');
const backEndCount$ = getCertCount(userCount, 'isBackEndCert');
function showAbout(req, res, next) {
const daysRunning = moment().diff(new Date('10/15/2014'), 'days');
Observable.combineLatest(
userCount$(),
userCount$({ isFrontEndCert: true }),
userCount$({ isDataVisCert: true }),
userCount$({ isBackEndCert: true }),
(
userCount,
frontEndCount = 0,
dataVisCount = 0,
backEndCount = 0
) => ({
userCount: numberWithCommas(userCount),
frontEndCount$,
dataVisCount$,
backEndCount$,
(frontEndCount = 0, dataVisCount = 0, backEndCount = 0) => ({
frontEndCount,
dataVisCount,
backEndCount
})
)
.doOnNext(({ userCount, frontEndCount, dataVisCount, backEndCount }) => {
.doOnNext(({ frontEndCount, dataVisCount, backEndCount }) => {
res.render('resources/about', {
userCount,
frontEndCount,
dataVisCount,
backEndCount,

View File

@ -1,4 +1,5 @@
import Rx from 'rx';
import Rx, { AsyncSubject, Observable } from 'rx';
import moment from 'moment';
import debugFactory from 'debug';
const debug = debugFactory('fcc:rxUtils');
@ -31,3 +32,22 @@ export function observeQuery(Model, method, query) {
export function observeMethod(context, methodName) {
return Rx.Observable.fromNodeCallback(context[methodName], context);
}
// timeChache(amount: Number, unit: String) => Observable
export function timeCache(time, unit) {
const source = this;
let cache;
let expireCacheAt;
return Observable.create(observable => {
// if there is no expire time set
// or if expireCacheAt is smaller than now,
// set new expire time in MS and create new subscription to source
if (!expireCacheAt || expireCacheAt < Date.now()) {
// set expire in ms;
expireCacheAt = moment().add(time, unit).valueOf();
cache = new AsyncSubject();
source.subscribe(cache);
}
return cache.subscribe(observable);
});
}

View File

@ -9,14 +9,6 @@ block content
span.tag Established:&#9;
span.text-primary #{daysRunning}
| days ago
li
span.tag Population:&#9;
span.text-primary #{userCount}
| campers
li
span.tag Completed:&#9;
span.text-primary #{globalCompletedCount}
| challenges
li.nowrap
span.tag Donated:&#9;
span.text-primary $850,000