From ea3f16128942ebd582c0b9e588ccbc46fca4e999 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 20 Aug 2013 23:55:43 -0400 Subject: [PATCH] static-groups: migrate user & groups initial subscription code to async, laying groudnwork for no-subscription --- src/app/index.coffee | 145 +++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 69 deletions(-) diff --git a/src/app/index.coffee b/src/app/index.coffee index 4090df0157..a2b95c7023 100644 --- a/src/app/index.coffee +++ b/src/app/index.coffee @@ -22,68 +22,7 @@ misc.viewHelpers view _ = require('lodash') algos = require 'habitrpg-shared/script/algos' - - -### - Subscribe to the user, the users's party (meta info like party name, member ids, etc), and the party's members. 3 subscriptions. -### -setupSubscriptions = (page, model, params, next, cb) -> - uuid = model.get('_userId') or model.session.userId # see http://goo.gl/TPYIt - selfQ = model.query('users').withId(uuid) #keep this for later - - # Note: due to https://github.com/codeparty/racer/issues/57, this has to come at the very beginning. The more limited - # the returned fields in motifs, the sooner they must come in fetch / subscribes. - publicGroupsQuery = model.query('groups').publicGroups() - myGroupsQuery = model.query('groups').withMember(uuid) - model.fetch publicGroupsQuery, myGroupsQuery, (err, publicGroups, groups) -> - return next(err) if err - finished = (descriptors, paths) -> - # Add public "Tavern" guild in - descriptors.unshift('groups.habitrpg'); paths.unshift('_habitRPG') - - # Subscribe to each descriptor - model.subscribe.apply model, descriptors.concat -> - [err, refs] = [arguments[0], arguments] - return next(err) if err - _.each paths, (path, idx) -> model.ref path, refs[idx+1]; true - unless model.get('_user') - console.error "User not found - this shouldn't be happening!" - return page.redirect('/logout') #delete model.session.userId - return cb() - - # Get public groups first, order most-to-least # subscribers - model.set '_publicGroups', _.sortBy(publicGroups.get(), (g) -> -_.size(g.members)) - - groupsObj = groups.get() - - # (1) Solo player - return finished([selfQ], ['_user']) if _.isEmpty(groupsObj) - - ## (2) Party or Guild has members, fetch those users too - # Subscribe to the groups themselves. We separate them by _party, _guilds, and _habitRPG (the "global" guild). - groupsInfo = _.reduce groupsObj, ((m,g)-> - if g.type is 'guild' then m.guildIds.push(g.id) else m.partyId = g.id - m.members = m.members.concat(g.members) - m - ), {guildIds:[], partyId:null, members:[]} - - # Fetch, not subscribe. There's nothing dynamic we need from members, just the the Group (below) which includes chat, challenges, etc - model.query('users').publicInfo(groupsInfo.members).fetch (err, members) -> - return next(err) if err - # we need _members as an object in the view, so we can iterate over _party.members as :id, and access _members[:id] for the info - mObj = members.get() - model.set "_members", _.object(_.pluck(mObj,'id'), mObj) - model.set "_membersArray", mObj - - # Note - selfQ *must* come after membersQ in subscribe, otherwise _user will only get the fields restricted by party-members in store.coffee. Strang bug, but easy to get around - descriptors = [selfQ]; paths = ['_user'] - if groupsInfo.partyId - descriptors.unshift model.query('groups').withIds(groupsInfo.partyId) - paths.unshift '_party' - unless _.isEmpty(groupsInfo.guildIds) - descriptors.unshift model.query('groups').withIds(groupsInfo.guildIds) - paths.unshift '_guilds' - finished descriptors, paths +async = require 'async' # ========== ROUTES ========== @@ -92,13 +31,81 @@ get '/', (page, model, params, next) -> return page.redirect '/' if page.params?.query?.play? # removed force-ssl (handled in nginx), see git for code - setupSubscriptions page, model, params, next, -> - require('./items').server(model) - #refLists - _.each ['habit', 'daily', 'todo', 'reward'], (type) -> - model.refList "_#{type}List", "_user.tasks", "_user.#{type}Ids" - true - page.render() + + ### + Subscribe to the user, the users's party (meta info like party name, member ids, etc), and the party's members. 3 subscriptions. + ### + uuid = model.get('_userId') or model.session.userId # see http://goo.gl/TPYIt + selfQ = model.query('users').withId(uuid) #keep this for later + # Note: due to https://github.com/codeparty/racer/issues/57, this has to come at the very beginning. The more limited + # the returned fields in motifs, the sooner they must come in fetch / subscribes. + publicGroupsQuery = model.query('groups').publicGroups() + myGroupsQuery = model.query('groups').withMember(uuid) + + # Note - selfQ *must* come after membersQ in subscribe, otherwise _user will only get the fields restricted by party-members in store.coffee. Strang bug, but easy to get around + descriptors = [selfQ]; paths = ['_user'] + async.waterfall [ + (cb) -> + model.fetch publicGroupsQuery, myGroupsQuery, cb + + (publicGroups, groups, cb) -> + # Get public groups first, order most-to-least # subscribers + model.set '_publicGroups', _.sortBy(publicGroups.get(), (g) -> -_.size(g.members)) + + groupsObj = groups.get() + + # (1) Solo player + return cb(true) if _.isEmpty(groupsObj) # passing in `true` breaks out of async.waterfall + + ## (2) Party or Guild has members, fetch those users too + # Subscribe to the groups themselves. We separate them by _party, _guilds, and _habitRPG (the "global" guild). + groupsInfo = _.reduce groupsObj, ((m,g)-> + if g.type is 'guild' then m.guildIds.push(g.id) else m.partyId = g.id + m.members = m.members.concat(g.members) + m + ), {guildIds:[], partyId:null, members:[]} + + # Fetch, not subscribe. There's nothing dynamic we need from members, just the the Group (below) which includes chat, challenges, etc + model.query('users').publicInfo(groupsInfo.members).fetch (err, members) -> cb(err, members, groupsInfo) + + (members, groupsInfo, cb) -> + # we need _members as an object in the view, so we can iterate over _party.members as :id, and access _members[:id] for the info + mObj = members.get() + model.set "_members", _.object(_.pluck(mObj,'id'), mObj) + model.set "_membersArray", mObj + + + if groupsInfo.partyId + descriptors.unshift model.query('groups').withIds(groupsInfo.partyId) + paths.unshift '_party' + unless _.isEmpty(groupsInfo.guildIds) + descriptors.unshift model.query('groups').withIds(groupsInfo.guildIds) + paths.unshift '_guilds' + cb() + + ], (err) -> + return next(err) if (err and err isnt true) #FIXME page.render err somehow? + + # Add public "Tavern" guild in + descriptors.unshift('groups.habitrpg'); paths.unshift('_habitRPG') + + # Subscribe to each descriptor + model.subscribe.apply model, descriptors.concat -> + [err, refs] = [arguments[0], arguments] + return next(err) if err + _.each paths, (path, idx) -> model.ref path, refs[idx+1]; true + unless model.get('_user') + console.error "User not found - this shouldn't be happening!" + return page.redirect('/logout') #delete model.session.userId + + + require('./items').server(model) + #refLists + _.each ['habit', 'daily', 'todo', 'reward'], (type) -> + model.refList "_#{type}List", "_user.tasks", "_user.#{type}Ids" + true + page.render() + # ========== CONTROLLER FUNCTIONS ==========