diff --git a/src/__tests__/index-test.js b/src/__tests__/index-test.js index d4dbb68..76c1468 100644 --- a/src/__tests__/index-test.js +++ b/src/__tests__/index-test.js @@ -4,12 +4,12 @@ import mongoose from 'mongoose'; import MongodbMemoryServer from 'mongodb-memory-server'; import { autoIncrement } from '..'; -let connection; // May require additional time for downloading MongoDB binaries jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; mongoose.Promise = global.Promise; let mongoServer; +let connection; // const opts = { useMongoClient: true }; beforeAll(async () => { @@ -51,12 +51,12 @@ afterEach(async () => { describe('mongoose-auto-increment', () => { it('increment the _id field on validate', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, 'User'); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -70,13 +70,13 @@ describe('mongoose-auto-increment', () => { }); it('increment the _id field on save', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, 'User'); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -89,13 +89,13 @@ describe('mongoose-auto-increment', () => { }); it('increment the specified field instead', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, { model: 'User', field: 'userId' }); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, { model: 'User', field: 'userId' }); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -109,12 +109,12 @@ describe('mongoose-auto-increment', () => { }); it('no duplicate key errors when creating docs in parallel', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, { model: 'User', field: 'userId' }); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, { model: 'User', field: 'userId' }); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -132,13 +132,13 @@ describe('mongoose-auto-increment', () => { }); it('start counting at specified number', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, { model: 'User', startAt: 3 }); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, { model: 'User', startAt: 3 }); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -152,12 +152,12 @@ describe('mongoose-auto-increment', () => { }); it('increment by the specified amount', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, { model: 'User', incrementBy: 5 }); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, { model: 'User', incrementBy: 5 }); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -167,7 +167,7 @@ describe('mongoose-auto-increment', () => { await user2.save(); expect(() => { - userSchema.plugin(autoIncrement); + UserSchema.plugin(autoIncrement); }).toThrowError('model must be set'); expect(user1._id).toBe(0); @@ -176,16 +176,16 @@ describe('mongoose-auto-increment', () => { describe('with incrementor groups', () => { it('increment the specified field within the groupingField instead', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, { + UserSchema.plugin(autoIncrement, { model: 'User', field: 'userId', groupingField: 'dept', }); - const User = connection.model('User', userSchema); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -205,13 +205,13 @@ describe('mongoose-auto-increment', () => { }); it('should not allow grouping fields with _id as the field', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); try { - userSchema.plugin(autoIncrement, { + UserSchema.plugin(autoIncrement, { model: 'User', groupingField: 'dept', }); @@ -225,12 +225,12 @@ describe('mongoose-auto-increment', () => { describe('nextCount() helper function', () => { it('nextCount should return the next count from document', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, 'User'); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -250,12 +250,12 @@ describe('mongoose-auto-increment', () => { }); it('nextCount should return the next count from model', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, 'User'); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -275,16 +275,16 @@ describe('mongoose-auto-increment', () => { }); it('with incrementor groups return the next count', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, { + UserSchema.plugin(autoIncrement, { model: 'User', field: 'userId', groupingField: 'dept', }); - const User = connection.model('User', userSchema); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -306,12 +306,12 @@ describe('mongoose-auto-increment', () => { describe('resetCount() helper function', () => { it('should reset count via doc method', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, 'User'); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user = new User({ name: 'Charlie', dept: 'Support' }); @@ -328,12 +328,12 @@ describe('mongoose-auto-increment', () => { }); it('should reset count via Model method', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ name: String, dept: String, }); - userSchema.plugin(autoIncrement, 'User'); - const User = connection.model('User', userSchema); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user = new User({ name: 'Charlie', dept: 'Support' }); @@ -351,17 +351,17 @@ describe('mongoose-auto-increment', () => { }); it('with string field and output filter increment the counter value only once', async () => { - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ orderNumber: Number, name: String, dept: String, }); - userSchema.plugin(autoIncrement, { + UserSchema.plugin(autoIncrement, { model: 'User', field: 'orderNumber', outputFilter: value => value * 100, }); - const User = connection.model('User', userSchema); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); @@ -397,16 +397,16 @@ describe('mongoose-auto-increment', () => { { _id, count: 79, field: 'orderNumber', model: 'User' }, ]); - const userSchema = new mongoose.Schema({ + const UserSchema = new mongoose.Schema({ orderNumber: Number, name: String, dept: String, }); - userSchema.plugin(autoIncrement, { + UserSchema.plugin(autoIncrement, { model: 'User', field: 'orderNumber', }); - const User = connection.model('User', userSchema); + const User = connection.model('User', UserSchema); await User.ensureIndexes(); const user1 = new User({ name: 'Charlie', dept: 'Support' }); diff --git a/src/__tests__/parallel-test.js b/src/__tests__/parallel-test.js new file mode 100644 index 0000000..492fa73 --- /dev/null +++ b/src/__tests__/parallel-test.js @@ -0,0 +1,98 @@ +// @flow + +import mongoose from 'mongoose'; +import MongodbMemoryServer from 'mongodb-memory-server'; +import { autoIncrement } from '..'; + +// May require additional time for downloading MongoDB binaries +jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; +mongoose.Promise = global.Promise; + +let mongoServer; +let connection; + +beforeAll(async () => { + mongoServer = new MongodbMemoryServer(); + const mongoUrl = await mongoServer.getConnectionString(); + + connection = await mongoose + .createConnection(mongoUrl, { + autoReconnect: true, + reconnectInterval: 100, + reconnectTries: Number.MAX_VALUE, + }) + // $FlowFixMe + .catch(() => {}); + connection.on('error', (...args) => console.error(...args)); +}); + +afterAll(() => { + mongoose.disconnect(); + mongoServer.stop(); +}); + +describe('parallel writing', () => { + it('check that autoinc works correctly for _id', async () => { + const runInParallel = 500; + + const UserSchema = new mongoose.Schema({ + name: String, + dept: String, + }); + UserSchema.plugin(autoIncrement, 'User'); + const User = connection.model('User', UserSchema); + + async function createUserAsync() { + return User.create({ + name: `Person ${Math.floor(Math.random() * 10000)}`, + email: `mail+${Math.floor(Math.random() * 10000)}@pad.co.uk`, + }); + } + + const p = []; + for (let i = 0; i < runInParallel; i++) { + p.push(createUserAsync()); + } + expect(p.length).toBe(runInParallel); + + const docs = await Promise.all(p); + + const uniqIds = new Set(); + for (let i = 0; i < runInParallel; i++) { + uniqIds.add(docs[i]._id.toString()); + } + expect(uniqIds.size).toBe(runInParallel); + }); + + it('check that autoinc works correctly for customField', async () => { + const runInParallel = 500; + + const UserPidSchema = new mongoose.Schema({ + name: String, + dept: String, + }); + UserPidSchema.plugin(autoIncrement, { model: 'UserPid', field: 'pid' }); + const UserPid = connection.model('UserPid', UserPidSchema); + + async function createUserPidAsync() { + return UserPid.create({ + name: `Person ${Math.floor(Math.random() * 10000)}`, + email: `mail+${Math.floor(Math.random() * 10000)}@pad.co.uk`, + }); + } + + const p = []; + for (let i = 0; i < runInParallel; i++) { + p.push(createUserPidAsync()); + } + expect(p.length).toBe(runInParallel); + + const docs = await Promise.all(p); + + const uniqPids = new Set(); + for (let i = 0; i < runInParallel; i++) { + uniqPids.add(docs[i].pid); + } + expect(uniqPids.size).toBe(runInParallel); + }); +}); diff --git a/src/index.js b/src/index.js index 96fb148..3aa9f49 100755 --- a/src/index.js +++ b/src/index.js @@ -52,7 +52,7 @@ counterSchema.index( export function initialize(): void { console.log( - `MongooseAutoIncrement.initialize() method is depricated. ` + + `MongooseAutoIncrement.initialize() method is deprecated. ` + `Just remove this method, it not required anymore.` ); }