Trifle
GitHub
Trifle::Stats / Drivers / Mongo
Learn in depth about Mongo driver implementation.

Mongo

Mongo driver uses mongo client gem to talk to database. It uses bulk_write and find operations for interacting with database.

Configuration

You can configure driver directly using mongo gem;

require 'mongo'

Trifle::Stats.configure do |config|
  config.driver = Trifle::Stats::Driver::Mongo.new(
    Mongo::Client.new('mongodb://mongo:27017/stats')
  )
end

Or if you are using mongoid, you can reuse its client setup.

Trifle::Stats.configure do |config|
  config.driver = Trifle::Stats::Driver::Mongo.new(
    Mongoid.client(:default)
  )
end

Setup

Mongo driver requires trifle_stats collection to be present. You can override collection_name when creating an instance of a driver.

You can create collection and index on your own or simply call setup! class method that does this for you. It creates a collection and adds an unique index on a key attribute.

Below is a setup and configuration for a custom database and a collection name.

client = Mongo::Client.new('mongodb://mongo:27017/stats')
Trifle::Stats::Driver::Mongo.setup!(
  Mongo::Client.new('mongodb://mongo:27017/stats'),
  collection_name: 'my_stats'
)

Trifle::Stats.configure do |config|
  config.driver = Trifle::Stats::Driver::Mongo.new(
    Mongo::Client.new('mongodb://mongo:27017/stats'),
    collection_name: 'my_stats'
  )
end

Driver

You can either use your default Mongoid client, or pass in instance of custom Mongo client.

irb(main):001:0> client = Mongo::Client.new('mongodb://mongo:27017/stats')
=> #<Mongo::Client:0x2080 cluster=#<Cluster topology=Single[mongo:27017] servers=[#<Server address=mongo:27017 STANDALONE pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>]>>
irb(main):002:0> driver = Trifle::Stats::Driver::Mongo.new(client)
=> #<Trifle::Stats::Driver::Mongo:0x000055949646adb8 @client=#<Mongo::Client:0x2080 cluster=#<Cluster topology=Single[mongo:27017] servers=[#<Server address=mongo:27017 STANDALONE pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>]>>, @collection_name="trifle_stats", @separator=...

Interaction

Once you create instance of a driver, you can use it to set, inc or get your data.

irb(main):003:0> driver.get(keys: [['test', 'now']])
=> [{}]

irb(main):004:0> driver.inc(keys: [['test', 'now']], count: 1, success: 1, error: 0)
=> #<Mongo::BulkWrite::Result:0x00005573a9148d28 @results={"n_modified"=>0, "n_upserted"=>1, "n_matched"=>0, "n"=>1, "upserted_ids"=>[BSON::ObjectId('62aabc4dca4d709bbea3719f')]}>
irb(main):005:0> driver.get(keys: [['test', 'now']])
=> [{"count"=>1, "error"=>0, "success"=>1}]

irb(main):006:0> driver.inc(keys: [['test', 'now']], count: 1, success: 0, error: 1, account: { count: 1 })
=> #<Mongo::BulkWrite::Result:0x00005573a8dcde78 @results={"n_modified"=>1, "n_upserted"=>0, "n_matched"=>1, "n"=>1, "upserted_ids"=>[]}>
irb(main):007:0> driver.get(keys: [['test', 'now']])
=> [{"count"=>2, "error"=>1, "success"=>1, "account"=>{"count"=>1}}]

Performance

All good here! set and inc are executed in one query and each key in keys is executed as a one bulk write operation. get fetches all keys in a single query.