예제 #1
0
    def test_mongos_max_staleness(self):
        # Sanity check that we're sending maxStalenessSeconds
        coll = client_context.client.pymongo_test.get_collection(
            "test", read_preference=SecondaryPreferred(max_staleness=120))
        # No error
        coll.find_one()

        coll = client_context.client.pymongo_test.get_collection(
            "test", read_preference=SecondaryPreferred(max_staleness=10))
        try:
            coll.find_one()
        except OperationFailure as exc:
            self.assertEqual(160, exc.code)
        else:
            self.fail("mongos accepted invalid staleness")

        coll = single_client(readPreference='secondaryPreferred',
                             maxStalenessSeconds=120).pymongo_test.test
        # No error
        coll.find_one()

        coll = single_client(readPreference='secondaryPreferred',
                             maxStalenessSeconds=10).pymongo_test.test
        try:
            coll.find_one()
        except OperationFailure as exc:
            self.assertEqual(160, exc.code)
        else:
            self.fail("mongos accepted invalid staleness")
예제 #2
0
    def test_query_and_read_mode_sharded_op_msg(self):
        """Test OP_MSG sends non-primary $readPreference and never $query."""
        server = MockupDB()
        server.autoresponds('ismaster', ismaster=True, msg='isdbgrid',
                            minWireVersion=2, maxWireVersion=6)
        server.run()
        self.addCleanup(server.stop)

        client = MongoClient(server.uri)
        self.addCleanup(client.close)

        read_prefs = (
            Primary(),
            SecondaryPreferred(),
            PrimaryPreferred(),
            Secondary(),
            Nearest(),
            SecondaryPreferred([{'tag': 'value'}]),)

        for query in ({'a': 1}, {'$query': {'a': 1}},):
            for mode in read_prefs:
                collection = client.db.get_collection('test',
                                                      read_preference=mode)
                cursor = collection.find(query.copy())
                with going(next, cursor):
                    request = server.receives()
                    # Command is not nested in $query.
                    request.assert_matches(OpMsg(
                        SON([('find', 'test'),
                             ('filter', {'a': 1}),
                             ('$readPreference', mode.document)])))

                    request.replies({'cursor': {'id': 0, 'firstBatch': [{}]}})
예제 #3
0
    def test_maybe_add_read_preference(self):

        # Primary doesn't add $readPreference
        out = _maybe_add_read_preference({}, Primary())
        self.assertEqual(out, {})

        pref = PrimaryPreferred()
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))
        pref = PrimaryPreferred(tag_sets=[{'dc': 'nyc'}])
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))

        pref = Secondary()
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))
        pref = Secondary(tag_sets=[{'dc': 'nyc'}])
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))

        # SecondaryPreferred without tag_sets or max_staleness doesn't add
        # $readPreference
        pref = SecondaryPreferred()
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(out, {})
        pref = SecondaryPreferred(tag_sets=[{'dc': 'nyc'}])
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))
        pref = SecondaryPreferred(max_staleness=120)
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))

        pref = Nearest()
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))
        pref = Nearest(tag_sets=[{'dc': 'nyc'}])
        out = _maybe_add_read_preference({}, pref)
        self.assertEqual(
            out, SON([("$query", {}), ("$readPreference", pref.document)]))

        criteria = SON([("$query", {}), ("$orderby", SON([("_id", 1)]))])
        pref = Nearest()
        out = _maybe_add_read_preference(criteria, pref)
        self.assertEqual(
            out,
            SON([("$query", {}), ("$orderby", SON([("_id", 1)])),
                 ("$readPreference", pref.document)]))
        pref = Nearest(tag_sets=[{'dc': 'nyc'}])
        out = _maybe_add_read_preference(criteria, pref)
        self.assertEqual(
            out,
            SON([("$query", {}), ("$orderby", SON([("_id", 1)])),
                 ("$readPreference", pref.document)]))
예제 #4
0
 def create(self, name: str) -> Client:
     client = self.clients.get(name)
     if client != None:
         return client
     else:
         opts = self.load_options(name)
         if opts == None:
             return
         mode = Primary()
         if opts.read_preference == READ_PREFERENCE_PRIMARY_PREFERRED:
             mode = PrimaryPreferred()
         elif opts.read_preference == READ_PREFERENCE_SECONDARY:
             mode = Secondary()
         elif opts.read_preference == READ_PREFERENCE_SECONDARY_PREFERRED:
             mode = SecondaryPreferred()
         elif opts.read_preference == READ_PREFERENCE_NEAREST:
             mode = Nearest()
         kwargs = {
             "read_preference" : mode,
             "maxPoolSize" : opts.max_pool_size,
             "minPoolSize" : opts.min_pool_size,
             "socketTimeoutMS" : opts.socket_time_out,
             "connectTimeoutMS" : opts.connect_time_out
         }
         _client = MongoClient(host=opts.uri, **kwargs)
         client = Client(db=name, c=_client, opts=opts)
         self.clients.set(name, client)
         return client
    def test_mongos(self):
        shard = client_context.client.config.shards.find_one()['host']
        num_members = shard.count(',') + 1
        if num_members == 1:
            raise SkipTest("Need a replica set shard to test.")
        coll = client_context.client.pymongo_test.get_collection(
            "test",
            write_concern=WriteConcern(w=num_members))
        coll.drop()
        res = coll.insert_many([{} for _ in range(5)])
        first_id = res.inserted_ids[0]
        last_id = res.inserted_ids[-1]

        # Note - this isn't a perfect test since there's no way to
        # tell what shard member a query ran on.
        for pref in (Primary(),
                     PrimaryPreferred(),
                     Secondary(),
                     SecondaryPreferred(),
                     Nearest()):
            qcoll = coll.with_options(read_preference=pref)
            results = list(qcoll.find().sort([("_id", 1)]))
            self.assertEqual(first_id, results[0]["_id"])
            self.assertEqual(last_id, results[-1]["_id"])
            results = list(qcoll.find().sort([("_id", -1)]))
            self.assertEqual(first_id, results[-1]["_id"])
            self.assertEqual(last_id, results[0]["_id"])
예제 #6
0
    def test_query_and_read_mode_sharded_op_query(self):
        server = MockupDB()
        server.autoresponds('ismaster', ismaster=True, msg='isdbgrid',
                            minWireVersion=2, maxWireVersion=5)
        server.run()
        self.addCleanup(server.stop)

        client = MongoClient(server.uri)
        self.addCleanup(client.close)

        modes_without_query = (
            Primary(),
            SecondaryPreferred(),)

        modes_with_query = (
            PrimaryPreferred(),
            Secondary(),
            Nearest(),
            SecondaryPreferred([{'tag': 'value'}]),)

        find_command = SON([('find', 'test'), ('filter', {'a': 1})])
        for query in ({'a': 1}, {'$query': {'a': 1}},):
            for mode in modes_with_query + modes_without_query:
                collection = client.db.get_collection('test',
                                                      read_preference=mode)
                cursor = collection.find(query.copy())
                with going(next, cursor):
                    request = server.receives()
                    if mode in modes_without_query:
                        # Filter is hoisted out of $query.
                        request.assert_matches(Command(find_command))
                        self.assertFalse('$readPreference' in request)
                    else:
                        # Command is nested in $query.
                        request.assert_matches(Command(
                            SON([('$query', find_command),
                                 ('$readPreference', mode.document)])))

                    request.replies({'cursor': {'id': 0, 'firstBatch': [{}]}})
class TestReadPreferenceObjects(unittest.TestCase):
    prefs = [Primary(),
             Secondary(),
             Nearest(tag_sets=[{'a': 1}, {'b': 2}]),
             SecondaryPreferred(max_staleness=30)]

    def test_pickle(self):
        for pref in self.prefs:
            self.assertEqual(pref, pickle.loads(pickle.dumps(pref)))

    def test_copy(self):
        for pref in self.prefs:
            self.assertEqual(pref, copy.copy(pref))
    def test_query_and_read_mode_sharded(self):
        server = MockupDB()
        server.autoresponds('ismaster', ismaster=True, msg='isdbgrid')
        server.run()
        self.addCleanup(server.stop)

        client = MongoClient(server.uri)
        self.addCleanup(client.close)

        modes_without_query = (
            Primary(),
            SecondaryPreferred(),)

        modes_with_query = (
            PrimaryPreferred(),
            Secondary(),
            Nearest(),
            SecondaryPreferred([{'tag': 'value'}]),)

        for query in ({'a': 1}, {'$query': {'a': 1}},):
            for mode in modes_with_query + modes_without_query:
                collection = client.db.get_collection('test',
                                                      read_preference=mode)
                cursor = collection.find(query.copy())
                with going(next, cursor):
                    request = server.receives(OpQuery)
                    if mode in modes_without_query:
                        # Query is not edited: {'a': 1} is not nested in $query,
                        # {'$query': {'a': 1}} is not hoisted.
                        request.assert_matches(query)
                        self.assertFalse('$readPreference' in request)
                    else:
                        # {'a': 1} is *always* nested in $query.
                        request.assert_matches({
                            '$query': {'a': 1},
                            '$readPreference': mode.document
                        })

                    request.replies({})
예제 #9
0
    def test_read_preference_document(self):

        pref = Primary()
        self.assertEqual(pref.document, {'mode': 'primary'})

        pref = PrimaryPreferred()
        self.assertEqual(pref.document, {'mode': 'primaryPreferred'})
        pref = PrimaryPreferred(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'primaryPreferred',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = PrimaryPreferred(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(
            pref.document, {
                'mode': 'primaryPreferred',
                'tags': [{
                    'dc': 'sf'
                }],
                'maxStalenessSeconds': 30
            })

        pref = Secondary()
        self.assertEqual(pref.document, {'mode': 'secondary'})
        pref = Secondary(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'secondary',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = Secondary(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(pref.document, {
            'mode': 'secondary',
            'tags': [{
                'dc': 'sf'
            }],
            'maxStalenessSeconds': 30
        })

        pref = SecondaryPreferred()
        self.assertEqual(pref.document, {'mode': 'secondaryPreferred'})
        pref = SecondaryPreferred(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'secondaryPreferred',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = SecondaryPreferred(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(
            pref.document, {
                'mode': 'secondaryPreferred',
                'tags': [{
                    'dc': 'sf'
                }],
                'maxStalenessSeconds': 30
            })

        pref = Nearest()
        self.assertEqual(pref.document, {'mode': 'nearest'})
        pref = Nearest(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'nearest',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = Nearest(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(pref.document, {
            'mode': 'nearest',
            'tags': [{
                'dc': 'sf'
            }],
            'maxStalenessSeconds': 30
        })

        with self.assertRaises(TypeError):
            Nearest(max_staleness=1.5)  # Float is prohibited.

        with self.assertRaises(ValueError):
            Nearest(max_staleness=0)

        with self.assertRaises(ValueError):
            Nearest(max_staleness=-2)
예제 #10
0
    def test_read_preference_document(self):

        pref = Primary()
        self.assertEqual(pref.document, {'mode': 'primary'})

        pref = PrimaryPreferred()
        self.assertEqual(pref.document, {'mode': 'primaryPreferred'})
        pref = PrimaryPreferred(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'primaryPreferred',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = PrimaryPreferred(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(
            pref.document, {
                'mode': 'primaryPreferred',
                'tags': [{
                    'dc': 'sf'
                }],
                'maxStalenessMS': 30000
            })

        pref = Secondary()
        self.assertEqual(pref.document, {'mode': 'secondary'})
        pref = Secondary(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'secondary',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = Secondary(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(pref.document, {
            'mode': 'secondary',
            'tags': [{
                'dc': 'sf'
            }],
            'maxStalenessMS': 30000
        })

        pref = SecondaryPreferred()
        self.assertEqual(pref.document, {'mode': 'secondaryPreferred'})
        pref = SecondaryPreferred(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'secondaryPreferred',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = SecondaryPreferred(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(
            pref.document, {
                'mode': 'secondaryPreferred',
                'tags': [{
                    'dc': 'sf'
                }],
                'maxStalenessMS': 30000
            })

        pref = Nearest()
        self.assertEqual(pref.document, {'mode': 'nearest'})
        pref = Nearest(tag_sets=[{'dc': 'sf'}])
        self.assertEqual(pref.document, {
            'mode': 'nearest',
            'tags': [{
                'dc': 'sf'
            }]
        })
        pref = Nearest(tag_sets=[{'dc': 'sf'}], max_staleness=30)
        self.assertEqual(pref.document, {
            'mode': 'nearest',
            'tags': [{
                'dc': 'sf'
            }],
            'maxStalenessMS': 30000
        })