Пример #1
0
        public string createIndex(object keys, object options)
        {
            BsonDocumentIndexKeysDefinition <BsonDocument> keysDefinitions =
                new BsonDocumentIndexKeysDefinition <BsonDocument>(keys.ToBsonDocument());

            CreateIndexOptions createIndexOptions = new CreateIndexOptions();

            return(this._collection.Indexes.CreateOne(keysDefinitions, createIndexOptions));
        }
Пример #2
0
        public bool Execute(IMongoDatabase database, MongoStorageOptions storageOptions, IMongoMigrationBag migrationBag)
        {
            var db = database.GetCollection <BsonDocument>($@"{storageOptions.Prefix}.statedata");

            var index = new BsonDocumentIndexKeysDefinition <BsonDocument>(new BsonDocument("Key", 1));

            db.Indexes.CreateOne(index);
            return(true);
        }
        // private methods
        private CreateIndexModel <BsonDocument> CreateCreateIndexModel()
        {
            var keysDefinition = new BsonDocumentIndexKeysDefinition <BsonDocument>(_keys);
            var options        = new CreateIndexOptions {
                Name = _name
            };

            return(new CreateIndexModel <BsonDocument>(keysDefinition, options));
        }
Пример #4
0
        private static void CreateJobIndex(IMongoCollection <BsonDocument> collection)
        {
            var index   = new BsonDocumentIndexKeysDefinition <BsonDocument>(new BsonDocument("JobId", -1));
            var options = new CreateIndexOptions
            {
                Name = "JobId",
            };

            collection.Indexes.CreateOne(index, options);
        }
Пример #5
0
        /// <summary>
        /// Backups the collection in database identified by collectionName.
        /// </summary>
        /// <param name="database">Referance to the mongo database.</param>
        /// <param name="collectionName">The name of the collection to backup.</param>
        /// <param name="backupCollectionName">Tha name of the backup collection.</param>
        protected virtual void BackupCollection(IMongoDatabase database, string collectionName, string backupCollectionName)
        {
            var aggregate = new BsonDocument(new Dictionary <string, object>
            {
                {
                    "aggregate", collectionName
                },
                {
                    "pipeline", new []
                    {
                        new Dictionary <string, object> {
                            { "$match", new BsonDocument() }
                        },
                        new Dictionary <string, object> {
                            { "$out", backupCollectionName }
                        }
                    }
                },
                {
                    "allowDiskUse", true
                },
                {
                    // As of MongoDB 3.4 cursor is no longer
                    //  optional, but can be set to "empty".
                    // https://docs.mongodb.com/manual/reference/command/aggregate/
                    "cursor", new BsonDocument()
                }
            });

            var serverStatus = database.RunCommand <BsonDocument>(new BsonDocument("buildinfo", 1));

            if (serverStatus.Contains("version"))
            {
                var version = Version.Parse(serverStatus["version"].AsString);
                if (version < new Version(2, 6))
                {
                    throw new InvalidOperationException("Hangfire.Mongo is not able to backup collections in MongoDB running a version prior to 2.6");
                }
                if (version >= new Version(3, 2))
                {
                    // The 'bypassDocumentValidation' was introduced in version 3.2
                    // https://docs.mongodb.com/manual/release-notes/3.2/#rel-notes-document-validation
                    aggregate["bypassDocumentValidation"] = true;
                }
            }

            var dbSource = database.GetCollection <BsonDocument>(collectionName);
            var indexes  = dbSource.Indexes.List().ToList().Where(idx => idx["name"] != "_id_").ToList();

            if (indexes.Any())
            {
                var dbBackup = database.GetCollection <BsonDocument>(backupCollectionName);
                foreach (var index in indexes)
                {
                    var newIndex     = new BsonDocumentIndexKeysDefinition <BsonDocument>(index["key"].AsBsonDocument);
                    var newIndexKeys = index.Names.ToList();

                    var newOptions = new CreateIndexOptions();


                    foreach (var key in newIndexKeys)
                    {
                        switch (key)
                        {
                        case "v": newOptions.Version = index[key].AsInt32; break;

                        case "name": newOptions.Name = index[key].AsString; break;

                        case "unique": newOptions.Unique = index[key].AsBoolean; break;

                        case "sparse": newOptions.Sparse = index[key].AsBoolean; break;

                        case "expireAfterSeconds": newOptions.ExpireAfter = TimeSpan.FromSeconds(index[key].AsInt64); break;

                        case "background": newOptions.Background = index[key].AsBoolean; break;

                        case "textIndexVersion": newOptions.TextIndexVersion = index[key].AsInt32; break;

                        case "default_language": newOptions.DefaultLanguage = index[key].AsString; break;

                        case "language_override": newOptions.LanguageOverride = index[key].AsString; break;

                        case "weights": newOptions.Weights = index[key].AsBsonDocument; break;

                        case "min": newOptions.Min = index[key].AsDouble; break;

                        case "max": newOptions.Max = index[key].AsDouble; break;

                        case "bits": newOptions.Bits = index[key].AsInt32; break;

                        case "2dsphereIndexVersion": newOptions.SphereIndexVersion = index[key].AsInt32; break;

                        case "bucketSize": newOptions.BucketSize = index[key].AsDouble; break;
                        }
                    }

                    dbBackup.Indexes.CreateOne(newIndex, newOptions);
                }
            }

            database.RunCommand(new BsonDocumentCommand <BsonDocument>(aggregate));
        }
        /// <summary>
        /// Backups the collection in database identified by collectionName.
        /// </summary>
        /// <param name="database">Referance to the mongo database.</param>
        /// <param name="collectionName">The name of the collection to backup.</param>
        /// <param name="backupCollectionName">Tha name of the backup collection.</param>
        protected virtual void BackupCollection(IMongoDatabase database, string collectionName, string backupCollectionName)
        {
            var aggregate = new BsonDocument(new Dictionary <string, object>
            {
                {
                    "aggregate", collectionName
                },
                {
                    "pipeline", new []
                    {
                        new Dictionary <string, object> {
                            { "$match", new BsonDocument() }
                        },
                        new Dictionary <string, object> {
                            { "$out", backupCollectionName }
                        }
                    }
                },
                {
                    "allowDiskUse", true
                },
                {
                    // As of MongoDB 3.4 cursor is no longer
                    //  optional, but can be set to "empty".
                    // https://docs.mongodb.com/manual/reference/command/aggregate/
                    "cursor", new BsonDocument()
                }
            });

            var serverStatus = database.RunCommand <BsonDocument>(new BsonDocument("serverStatus", 1));

            if (serverStatus.Contains("version"))
            {
                var version = Version.Parse(serverStatus["version"].AsString);
                if (version < new Version(2, 6))
                {
                    throw new InvalidOperationException("Hangfire.Mongo is not able to backup collections in MongoDB running a version prior to 2.6");
                }
                if (version >= new Version(3, 2))
                {
                    // The 'bypassDocumentValidation' was introduced in version 3.2
                    // https://docs.mongodb.com/manual/release-notes/3.2/#rel-notes-document-validation
                    aggregate["bypassDocumentValidation"] = true;
                }
            }

            var dbSource = database.GetCollection <BsonDocument>(collectionName);
            var indexes  = dbSource.Indexes.List().ToList().Where(idx => idx["name"] != "_id_").ToList();

            if (indexes.Any())
            {
                var dbBackup = database.GetCollection <BsonDocument>(backupCollectionName);
                foreach (var index in indexes)
                {
                    var newIndex     = new BsonDocumentIndexKeysDefinition <BsonDocument>(index["key"].AsBsonDocument);
                    var newIndexKeys = index.Names.ToList();

                    var newOptions = new CreateIndexOptions();
                    foreach (var mapping in CreateIndexOptionsMapping.Where(m => newIndexKeys.Contains(m.Key)))
                    {
                        var prop = newOptions.GetType().GetTypeInfo().GetProperty(mapping.Name);
                        if (prop != null)
                        {
                            prop.SetValue(newOptions, mapping.Convert(index[mapping.Key].Value));
                        }
                    }
                    dbBackup.Indexes.CreateOne(newIndex, newOptions);
                }
            }

            database.RunCommand(new BsonDocumentCommand <BsonDocument>(aggregate));
        }
Пример #7
0
        async Task <IMongoCollection <BsonDocument> > GetCollection(Type sagaDataType, IEnumerable <ISagaCorrelationProperty> correlationProperties = null)
        {
            try
            {
                var collectionName  = _collectionNameResolver(sagaDataType);
                var mongoCollection = _mongoDatabase.GetCollection <BsonDocument>(collectionName);

                var dummy = _verifiedSagaDataTypes.GetOrAdd(sagaDataType, _ =>
                {
                    VerifyBsonSerializerFor(sagaDataType);
                    return(null);
                });

                if (correlationProperties == null)
                {
                    return(mongoCollection);
                }

                async Task CreateIndexes()
                {
                    if (!_automaticallyCreateIndexes)
                    {
                        return;
                    }

                    _log.Info("Initializing index for saga data {type} in collection {collectionName}", sagaDataType, collectionName);

                    foreach (var correlationProperty in correlationProperties)
                    {
                        // skip this, because there's already an index on 'Id', and it's mapped to '_id'
                        if (correlationProperty.PropertyName == nameof(ISagaData.Id))
                        {
                            continue;
                        }

                        _log.Debug("Creating index on property {propertyName} of {type}",
                                   correlationProperty.PropertyName, sagaDataType);

                        var index = new BsonDocument {
                            { correlationProperty.PropertyName, 1 }
                        };
                        var indexDef = new BsonDocumentIndexKeysDefinition <BsonDocument>(index);
                        await mongoCollection.Indexes.CreateOneAsync(indexDef, new CreateIndexOptions { Unique = true });
                    }

                    try
                    {
                        // try to remove any previously created indexes on 'Id'
                        //
                        // we're after this:
                        // {{ "v" : 2, "unique" : true, "key" : { "Id" : 1 }, "name" : "Id_1", "ns" : "rebus2_test__net45.SomeSagaData" }}
                        using (var cursor = await mongoCollection.Indexes.ListAsync())
                        {
                            while (await cursor.MoveNextAsync())
                            {
                                var indexes = cursor.Current;

                                foreach (var index in indexes)
                                {
                                    var isUnique = index.Contains("unique") && index["unique"].AsBoolean;

                                    var hasSingleIdKey = index.Contains("key") &&
                                                         index["key"].AsBsonDocument.Contains("Id") &&
                                                         index["key"].AsBsonDocument.Count() == 1 &&
                                                         index["key"].AsBsonDocument["Id"].AsInt32 == 1;

                                    if (isUnique && hasSingleIdKey)
                                    {
                                        // this is it!
                                        var name = index["name"].AsString;

                                        await mongoCollection.Indexes.DropOneAsync(name);
                                    }
                                }
                            }
                        }
                    }
                    catch { } //<ignore error here, because it is probably a race condition
                }

                var initializer = _collectionInitializers.GetOrAdd(sagaDataType, _ => new Lazy <Task>(CreateIndexes));

                await initializer.Value;

                return(mongoCollection);
            }
            catch (BsonSchemaValidationException)
            {
                throw;
            }
            catch (Exception exception)
            {
                throw new RebusApplicationException(exception, $"Could not get MongoCollection for saga data of type {sagaDataType}");
            }
        }