Activity with aggregation

This PR implements activities with aggregation.

I backed off delivering activities with such aggressive speed as before. The previous activities branch w/o aggregation would deliver activities immediately when routed. This implementation queues them into "buckets" where they can be processed.

The reason they are queued is because there are a fair amount of race conditions involved if you have multiple processes delivering and aggregating activities for the same routes and types. You can end up with accidentally duplicating aggregates in a user's feed, and also delivering multiple single-activities intermittently when they should have been aggregated.

The bucketed approach ensures that activities of the same route and type are queued in the same bucket, which means that they will be collected in serial by a single process, which eliminates all the race conditions. The reason there are multiple buckets instead of a single queue is because, since the point is to ensure only one process can collect the queue at one time, a single queue would mean activity collection cannot scale at all beyond one server. Since multiple buckets can be collected concurrently, we can increase the number of buckets to reflect the number of processes we have collecting activities, giving us the ability to scale activity performance with more hardware.

The activity servers find buckets to process through a polling mechanism. This (configurable) polling interval, while can intermittently give delays in collection, ensures masterless collection coordination (i.e., if any node suddenly drops out, activity collection should be able to continue with the remaining nodes with limited penalty). If we didn't poll, I think we'd need to establish more advanced cluster communication with the activity nodes, which I'm not sure is really necessary.