SlideShare a Scribd company logo
1 of 27
Download to read offline
Fun Teaching MongoDB
New Tricks
Robert J. Moore
President
Allanbank Consulting, Inc.

Robert.J.Moore@allanbank.com
Agenda
   Inspiration

   A Little Fun: MongoDB as
     ... a Coordination Service?
     ... a Message Broker?

   https://github.com/allanbank/mongodb-tricks
Disclaimer
 Don't try these at home
 They are hacks in the best sense

 Professional developer on an air gap
  laptop

 Enough! On with the fun
Inspiration - Topics
 Publish / Subscribe
     One writer, many readers


   MongoDB Capped Collection
   Tailable Cursor
   Can also have selectors
Inspiration - Topics
 Create a Capped Collection
   Acts like a ring buffer
 Tailable Cursor returns documents as
  they are added in the future

                              ...


                                      Cursor

                                    Document
Asynchronous Java Driver
 Website
   http://www.allanbank.com/mongodb-async-driver
 Focus on performance and usability
 Lower latency, higher throughput even under
  heavy thread contention
 Benefit when using the synchronous
  interface
 Greater benefit using the asynchronous
  interface
Asynchronous Java Driver
Performance




  http://www.allanbank.com/mongodb-async-driver/performance/ycsb.html
Coordination Service
 ZooKeeper
   Notification that something of interest
    changed
     Watches
   Track entities in a group
     Group Management
Watches
 Replica Set Oplog
   All Insert, Update, Delete operations
   Capped – Tailable cursors again
 Want to convert from the Oplog
   Different fields contain the _id of the
    document
Oplog Documents
 Insert
     { "ts" : { "t" : 1362958492000, "i" : 1 },
       "h" : NumberLong("5915409566571821368"), "v" : 2,
       "op" : "i",
       "ns" : "test.test",
       "o" : { "_id" : "513d189c8544eb2b5e000001" } }
 Delete
     { ... "op" : "d", ..., "b" : true,
        "o" : { "_id" : "513d189c8544eb2b5e000001" } }
 Update
     { ... "op" : "u", ...,
       "o2" : { "_id" : "513d189c8544eb2b5e000001" },
       "o" : { "$set" : { "i" : 1 } } }

Initialize a Watcher - Code
final DocumentAssignable wantQuery =
        or(
            where("ns").equals(ns)
             .and("op").in(constant("i"), constant("d"))
             .and("o._id").matches(myContext),
            where("ns").equals(ns)
             .and("op").equals("u")
             .and("o2._id").matches(myContext));

final Find.Builder builder = new Find.Builder();
if (myLastTs != null) {
    final DocumentBuilder tsQuery = BuilderFactory.start();
    tsQuery.push(myLastTs.getName())
              .add(myLastTs.withName(ComparisonOperator.GT.getToken()));

    builder.setQuery(and(tsQuery, wantQuery));
}
else {
    builder.setQuery(wantQuery);
}

builder.tailable();

MongoDatabase localDb = myMongoClient.getDatabase("local");
MongoCollection oplog = localDb.getCollection("oplog.rs");
myControls = oplog.streamingFind(new OpLogNotification(), builder.build());
Watcher - Code
Watcher watcher = new Watcher(client, collection,
        Pattern.compile(".*"), new WatchListener() {
            @Override
            public void changed(Operation op, String context,
                    Document document) {
                if (op == Operation.DELETE) {
                    System.out.println(context + ": " + op);
                }
                else {
                    System.out.println(context + ": " + op + ": "
                            + document);
                }
            }
        });
watcher.start();
Watcher Demo
Group Management
 Notification of:
    Adding a Group Member
    Removing a Group Member
        Or Group Member Disappears
 Combination of:
      Watcher
      Scheduled Task for Heartbeat
      Expire old members
Group Manager Client - Code
GroupManager manager = new GroupManager(executor, client, collection, rootContext);
manager.addListener(new GroupListener() {
    @Override
    public void memberRemoved(String context) {
        System.out.println(context + " - Removed");
    }

   @Override
   public void memberAdded(String context) {
       System.out.println(context + " - Added");
   }
});
manager.start();

final GroupMember member = manager.addMember();

// Faster cleanup, if we can.
Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        member.remove();
    }
});
Group Demo
Queues
 Divide and Conquer
   One writer, one reader


 MongoDB Capped Collection
 Want to “share” a Cursor
Restartable Cursors
  What if we had multiple applications passing the
   same “getmore” requests?
  “getmore” message references a cursor
struct {
    MsgHeader header;             // standard message header
    int32     ZERO;               // 0 - reserved for future use
    cstring   fullCollectionName; // "dbname.collectionname"
    int32     numberToReturn;     // number of documents to return
    int64     cursorID;           // cursorID from the OP_REPLY
}
http://docs.mongodb.org/meta-driver/latest/legacy/mongodb-wire-protocol/#op-get-more


  We need a way to save and restore the cursor
  Lets call them Restartable Cursors, but they don't
   exist, yet
Queues
    Create a Capped Collection
    Initialize a Tailable Cursor
    Share with multiple processes


                                  ...


                                                  Cursor

    Application 1 Application 2 Application 3   Document
Restartable Cursors
 Added the ability to:
    Persist an iterator or stream as a doument
    Halt or stop the iterator stream (after
     exhausting the already requested
     documents).
 For restart add the ability to restart the
  iterator or stream
 Allows conversion from an iterator to a
  stream and back.
Queues – Initialization Code
 Initialize a Tailable Cursor
 Share with multiple processes
   Find.Builder builder = new Find.Builder(BuilderFactory.start());
   builder.setTailable(true);
   builder.setAwaitData(false); // Sigh.
   MongoIterator<Document> cursor = collection.find(builder.build());

   // Graceful shutdown of the iterator locally but not on the server.
   cursor.stop();
   while (cursor.hasNext()) {
       System.out.println(cursor.next());
   }

   collection = db.getCollection("lookup");
   collection.delete(BuilderFactory.start().add("_id", collectionName));
   collection.insert(BuilderFactory.start().add("_id", collectionName)
           .add("cursor", cursor.asDocument()));
Queues – Consumer Code

   MongoCollection index = client.getDatabase(args[1]).getCollection(
           "lookup");
   Document queueLookupDoc = index.findOne(BuilderFactory.start().add(
           "_id", args[2]));
   DocumentElement cursorElement = queueLookupDoc.get(
           DocumentElement.class, "cursor");
   MongoIterator<Document> iter = client.restart(cursorElement
           .getDocument());

   long lastCount = 0;
   while (iter.hasNext()) {
       Document doc = iter.next();
       // Do stuff
   }
Queues Demo
Restartable Cursors - Gotcha
 Remember this: builder.setAwaitData(false); // Sigh.
 That masks a small issue...
Pin( long long cursorid ) :
    _cursorid( INVALID_CURSOR_ID ) {
    recursive_scoped_lock lock( ccmutex );
    ClientCursor *cursor = ClientCursor::find_inlock( cursorid, true );
    if ( cursor ) {
        uassert( 12051, "clientcursor already in use? driver problem?",
                 cursor->_pinValue < 100 );
        cursor->_pinValue += 100;
        _cursorid = cursorid;
    }
}


   Closes the cursor on the client
   https://jira.mongodb.org/browse/SERVER-8602
   https://github.com/allanbank/mongo/tree/concurrent_cursor_support
Final Thoughts
 Coordination Service
   Watchers
   Group Management
 Message Broker
   Topics
   Queues


 Remember the Disclaimer
Questions?



    Contact Information:
        Robert.J.Moore@allanbank.com
Fun Teaching MongoDB New Tricks

More Related Content

What's hot

2日間Fabricを触った俺が
 色々解説してみる
2日間Fabricを触った俺が
 色々解説してみる2日間Fabricを触った俺が
 色々解説してみる
2日間Fabricを触った俺が
 色々解説してみる
airtoxin Ishii
 

What's hot (20)

Git flowの活用事例
Git flowの活用事例Git flowの活用事例
Git flowの活用事例
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
 
凝集度と責務
凝集度と責務凝集度と責務
凝集度と責務
 
.NET 7におけるBlazorの新機能
.NET 7におけるBlazorの新機能.NET 7におけるBlazorの新機能
.NET 7におけるBlazorの新機能
 
はじめてのCF buildpack
はじめてのCF buildpackはじめてのCF buildpack
はじめてのCF buildpack
 
Spark & Zeppelin을 활용한 머신러닝 실전 적용기
Spark & Zeppelin을 활용한 머신러닝 실전 적용기Spark & Zeppelin을 활용한 머신러닝 실전 적용기
Spark & Zeppelin을 활용한 머신러닝 실전 적용기
 
Presentación Zoho ERP para empresas de Formación
Presentación Zoho ERP para empresas de FormaciónPresentación Zoho ERP para empresas de Formación
Presentación Zoho ERP para empresas de Formación
 
9장 도메인 주도 설계
9장 도메인 주도 설계9장 도메인 주도 설계
9장 도메인 주도 설계
 
ドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDDドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDD
 
モンスターストライクにおける負荷対策
モンスターストライクにおける負荷対策モンスターストライクにおける負荷対策
モンスターストライクにおける負荷対策
 
PHP7ではなくHack/HHVMを選ぶ理由
PHP7ではなくHack/HHVMを選ぶ理由PHP7ではなくHack/HHVMを選ぶ理由
PHP7ではなくHack/HHVMを選ぶ理由
 
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
 
Introduction to Microsoft Kaizala And How to Empower Your Mobile Workforce us...
Introduction to Microsoft Kaizala And How to Empower Your Mobile Workforce us...Introduction to Microsoft Kaizala And How to Empower Your Mobile Workforce us...
Introduction to Microsoft Kaizala And How to Empower Your Mobile Workforce us...
 
DI(依存性注入)について
DI(依存性注入)についてDI(依存性注入)について
DI(依存性注入)について
 
Data platform data pipeline(Airflow, Kubernetes)
Data platform data pipeline(Airflow, Kubernetes)Data platform data pipeline(Airflow, Kubernetes)
Data platform data pipeline(Airflow, Kubernetes)
 
事件風暴-領域建模
事件風暴-領域建模事件風暴-領域建模
事件風暴-領域建模
 
2日間Fabricを触った俺が
 色々解説してみる
2日間Fabricを触った俺が
 色々解説してみる2日間Fabricを触った俺が
 色々解説してみる
2日間Fabricを触った俺が
 色々解説してみる
 
Scalable web architecture
Scalable web architectureScalable web architecture
Scalable web architecture
 
【社内勉強会】弊社でGit!実案件での運用
【社内勉強会】弊社でGit!実案件での運用【社内勉強会】弊社でGit!実案件での運用
【社内勉強会】弊社でGit!実案件での運用
 
Java EE 再入門
Java EE 再入門Java EE 再入門
Java EE 再入門
 

Similar to Fun Teaching MongoDB New Tricks

JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
Qiangning Hong
 

Similar to Fun Teaching MongoDB New Tricks (20)

Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Back to Basics Webinar 2 - Your First MongoDB Application
Back to  Basics Webinar 2 - Your First MongoDB ApplicationBack to  Basics Webinar 2 - Your First MongoDB Application
Back to Basics Webinar 2 - Your First MongoDB Application
 
Back to Basics Webinar 2: Your First MongoDB Application
Back to Basics Webinar 2: Your First MongoDB ApplicationBack to Basics Webinar 2: Your First MongoDB Application
Back to Basics Webinar 2: Your First MongoDB Application
 
[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless
 
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
 
Mongoose and MongoDB 101
Mongoose and MongoDB 101Mongoose and MongoDB 101
Mongoose and MongoDB 101
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOS
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMS
 
Kerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit eastKerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit east
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Mongo db dla administratora
Mongo db dla administratoraMongo db dla administratora
Mongo db dla administratora
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Back to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDBBack to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDB
 
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
 
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Global objects in Node.pdf
Global objects in Node.pdfGlobal objects in Node.pdf
Global objects in Node.pdf
 
Kotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutinesKotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutines
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 

More from MongoDB

More from MongoDB (20)

MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB AtlasMongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
 
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
 
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
 
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDBMongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
 
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
 
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series DataMongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
 
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 MongoDB SoCal 2020: MongoDB Atlas Jump Start MongoDB SoCal 2020: MongoDB Atlas Jump Start
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
 
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
 
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
 
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
 
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your MindsetMongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
 
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas JumpstartMongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
 
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
 
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
 
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
 
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep DiveMongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
 
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & GolangMongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
 
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
 
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
 

Fun Teaching MongoDB New Tricks

  • 1. Fun Teaching MongoDB New Tricks Robert J. Moore President Allanbank Consulting, Inc. Robert.J.Moore@allanbank.com
  • 2. Agenda  Inspiration  A Little Fun: MongoDB as  ... a Coordination Service?  ... a Message Broker?  https://github.com/allanbank/mongodb-tricks
  • 3. Disclaimer  Don't try these at home  They are hacks in the best sense  Professional developer on an air gap laptop  Enough! On with the fun
  • 4. Inspiration - Topics  Publish / Subscribe  One writer, many readers  MongoDB Capped Collection  Tailable Cursor  Can also have selectors
  • 5. Inspiration - Topics  Create a Capped Collection  Acts like a ring buffer  Tailable Cursor returns documents as they are added in the future ... Cursor Document
  • 6. Asynchronous Java Driver  Website  http://www.allanbank.com/mongodb-async-driver  Focus on performance and usability  Lower latency, higher throughput even under heavy thread contention  Benefit when using the synchronous interface  Greater benefit using the asynchronous interface
  • 7. Asynchronous Java Driver Performance http://www.allanbank.com/mongodb-async-driver/performance/ycsb.html
  • 8. Coordination Service  ZooKeeper  Notification that something of interest changed  Watches  Track entities in a group  Group Management
  • 9. Watches  Replica Set Oplog  All Insert, Update, Delete operations  Capped – Tailable cursors again  Want to convert from the Oplog  Different fields contain the _id of the document
  • 10. Oplog Documents  Insert { "ts" : { "t" : 1362958492000, "i" : 1 }, "h" : NumberLong("5915409566571821368"), "v" : 2, "op" : "i", "ns" : "test.test", "o" : { "_id" : "513d189c8544eb2b5e000001" } }  Delete { ... "op" : "d", ..., "b" : true, "o" : { "_id" : "513d189c8544eb2b5e000001" } }  Update { ... "op" : "u", ..., "o2" : { "_id" : "513d189c8544eb2b5e000001" }, "o" : { "$set" : { "i" : 1 } } } 
  • 11. Initialize a Watcher - Code final DocumentAssignable wantQuery = or( where("ns").equals(ns) .and("op").in(constant("i"), constant("d")) .and("o._id").matches(myContext), where("ns").equals(ns) .and("op").equals("u") .and("o2._id").matches(myContext)); final Find.Builder builder = new Find.Builder(); if (myLastTs != null) { final DocumentBuilder tsQuery = BuilderFactory.start(); tsQuery.push(myLastTs.getName()) .add(myLastTs.withName(ComparisonOperator.GT.getToken())); builder.setQuery(and(tsQuery, wantQuery)); } else { builder.setQuery(wantQuery); } builder.tailable(); MongoDatabase localDb = myMongoClient.getDatabase("local"); MongoCollection oplog = localDb.getCollection("oplog.rs"); myControls = oplog.streamingFind(new OpLogNotification(), builder.build());
  • 12. Watcher - Code Watcher watcher = new Watcher(client, collection, Pattern.compile(".*"), new WatchListener() { @Override public void changed(Operation op, String context, Document document) { if (op == Operation.DELETE) { System.out.println(context + ": " + op); } else { System.out.println(context + ": " + op + ": " + document); } } }); watcher.start();
  • 14. Group Management  Notification of:  Adding a Group Member  Removing a Group Member  Or Group Member Disappears  Combination of:  Watcher  Scheduled Task for Heartbeat  Expire old members
  • 15. Group Manager Client - Code GroupManager manager = new GroupManager(executor, client, collection, rootContext); manager.addListener(new GroupListener() { @Override public void memberRemoved(String context) { System.out.println(context + " - Removed"); } @Override public void memberAdded(String context) { System.out.println(context + " - Added"); } }); manager.start(); final GroupMember member = manager.addMember(); // Faster cleanup, if we can. Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { member.remove(); } });
  • 17. Queues  Divide and Conquer  One writer, one reader  MongoDB Capped Collection  Want to “share” a Cursor
  • 18. Restartable Cursors  What if we had multiple applications passing the same “getmore” requests?  “getmore” message references a cursor struct { MsgHeader header; // standard message header int32 ZERO; // 0 - reserved for future use cstring fullCollectionName; // "dbname.collectionname" int32 numberToReturn; // number of documents to return int64 cursorID; // cursorID from the OP_REPLY } http://docs.mongodb.org/meta-driver/latest/legacy/mongodb-wire-protocol/#op-get-more  We need a way to save and restore the cursor  Lets call them Restartable Cursors, but they don't exist, yet
  • 19. Queues  Create a Capped Collection  Initialize a Tailable Cursor  Share with multiple processes ... Cursor Application 1 Application 2 Application 3 Document
  • 20. Restartable Cursors  Added the ability to:  Persist an iterator or stream as a doument  Halt or stop the iterator stream (after exhausting the already requested documents).  For restart add the ability to restart the iterator or stream  Allows conversion from an iterator to a stream and back.
  • 21. Queues – Initialization Code  Initialize a Tailable Cursor  Share with multiple processes Find.Builder builder = new Find.Builder(BuilderFactory.start()); builder.setTailable(true); builder.setAwaitData(false); // Sigh. MongoIterator<Document> cursor = collection.find(builder.build()); // Graceful shutdown of the iterator locally but not on the server. cursor.stop(); while (cursor.hasNext()) { System.out.println(cursor.next()); } collection = db.getCollection("lookup"); collection.delete(BuilderFactory.start().add("_id", collectionName)); collection.insert(BuilderFactory.start().add("_id", collectionName) .add("cursor", cursor.asDocument()));
  • 22. Queues – Consumer Code MongoCollection index = client.getDatabase(args[1]).getCollection( "lookup"); Document queueLookupDoc = index.findOne(BuilderFactory.start().add( "_id", args[2])); DocumentElement cursorElement = queueLookupDoc.get( DocumentElement.class, "cursor"); MongoIterator<Document> iter = client.restart(cursorElement .getDocument()); long lastCount = 0; while (iter.hasNext()) { Document doc = iter.next(); // Do stuff }
  • 24. Restartable Cursors - Gotcha  Remember this: builder.setAwaitData(false); // Sigh.  That masks a small issue... Pin( long long cursorid ) : _cursorid( INVALID_CURSOR_ID ) { recursive_scoped_lock lock( ccmutex ); ClientCursor *cursor = ClientCursor::find_inlock( cursorid, true ); if ( cursor ) { uassert( 12051, "clientcursor already in use? driver problem?", cursor->_pinValue < 100 ); cursor->_pinValue += 100; _cursorid = cursorid; } }  Closes the cursor on the client  https://jira.mongodb.org/browse/SERVER-8602  https://github.com/allanbank/mongo/tree/concurrent_cursor_support
  • 25. Final Thoughts  Coordination Service  Watchers  Group Management  Message Broker  Topics  Queues  Remember the Disclaimer
  • 26. Questions?  Contact Information: Robert.J.Moore@allanbank.com