Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Commit

Permalink
Merge a72e25c into 23dde25
Browse files Browse the repository at this point in the history
  • Loading branch information
braydonf committed Nov 13, 2017
2 parents 23dde25 + a72e25c commit 3422c6d
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 23 deletions.
120 changes: 120 additions & 0 deletions lib/models/cron.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use strict';

const assert = require('assert');
const mongoose = require('mongoose');

const CronJob = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
index: true
},
locked: {
type: Boolean,
required: true
},
lockedEnd: {
type: Date,
required: true
},
started: {
type: Date,
required: true
},
finished: {
type: Date,
required: false
},
data: {
type: String,
required: false
}
});

CronJob.statics.lock = function(name, expires, callback) {
const self = this;
const now = new Date();
const end = new Date(now.getTime() + expires);
assert(Number.isInteger(expires), 'Expires argument is expected');

function isDuplicate(err) {
return (err && err.code === 11000);
}

function getLock(done) {
const query = {
name: name,
locked: false
};
const sort = {};
const update = {
$set: {
name: name,
locked: true,
lockedEnd: end,
started: now
}
};
const options = {
new: true,
upsert: true,
writeConcern: 'majority'
};
self.collection.findAndModify(query, sort, update, options, (err, res) => {
if (isDuplicate(err)) {
return done(null, false);
} else if (err) {
return done(err, false);
}
done(null, true, res);
});
}

function getLockFromExpired(done) {
console.log('NOW', now);
const query = {
name: name,
locked: true,
lockedEnd: {
$lte: now
}
};
const sort = {};
const update = {
$set: {
name: name,
locked: true,
lockedEnd: end,
started: now
}
};
const options = {
new: true,
upsert: true,
writeConcern: 'majority'
};
self.collection.findAndModify(query, sort, update, options, (err, res) => {
if (isDuplicate(err)) {
return done(null, false);
} else if (err) {
return done(err, false);
}
done(null, true, res);
});
}

getLock((err, success, res) => {
if (err) {
return callback(err);
}
if (!success) {
return getLockFromExpired(callback);
}
callback(err, success, res);
});
};

module.exports = function(connection) {
return connection.model('CronJob', CronJob);
};
84 changes: 70 additions & 14 deletions lib/models/storage-event.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,99 @@
const mongoose = require('mongoose');
const utils = require('../utils');
/**
* Represents the history of storage related summary
* Represents the history of storage related summary
* statistics for buckets and their associated files
* @constructor
*/

var StorageEvent = new mongoose.Schema({
bucket: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Bucket',
required: true
},
bucketEntry: {
type: mongoose.Schema.Types.ObjectId,
ref: 'BucketEntry',
required: true
token: {
type: String,
required: false,
unique: true
},
user: {
type: String,
type: String,
ref: 'User',
required: true,
required: false,
validate: {
validator: value => utils.isValidEmail(value),
validator: value => utils.isValidEmail(value) || !value,
message: 'Invalid user email address'
}
},
client: {
type: String,
required: true
},
farmer: {
type: String,
required: true
},
timestamp: {
type: Date,
default: Date.now,
required: true
},
farmerEnd: {
type: Date,
required: false
},
userDeleted: {
type: Date,
required: false
},
downloadBandwidth: {
type: Number,
required: false
},
storage: {
type: Number,
type: Number,
required: false
},
shardHash: {
type: String,
required: false
},
clientReport: {
exchangeStart: {
type: Date,
required: false
},
exchangeEnd: {
type: Date,
required: false
},
exchangeResultCode: {
type: Number,
required: false
},
exchangeResultMessage: {
type: String,
required: false
}
},
farmerReport: {
exchangeStart: {
type: Date,
required: false
},
exchangeEnd: {
type: Date,
required: false
},
exchangeResultCode: {
type: Number,
required: false
},
exchangeResultMessage: {
type: String,
required: false
}
},
success: {
type: Boolean,
required: true,
default: false
}
});

Expand Down
122 changes: 122 additions & 0 deletions test/cron.unit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
'use strict';

const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');
const chaiDate = require('chai-datetime');
const mongoose = require('mongoose');

chai.use(chaiDate);
require('mongoose-types').loadTypes(mongoose);

const CronSchema = require('../lib/models/cron');

var Cron;
var connection;

before(function(done) {
connection = mongoose.createConnection(
'mongodb://127.0.0.1:27017/__storj-bridge-test',
function() {
Cron = CronSchema(connection);
Cron.remove({}, function() {
done();
});
}
);
});

after(function(done) {
connection.close(done);
});

describe('/Storage/models/Cron', function() {
const sandbox = sinon.sandbox.create();
afterEach(() => sandbox.restore());

describe('@constructor', function() {

it('should create new work', function (done) {
const now = new Date();
const end = new Date(now.getTime() + 1000);
const job = new Cron({
name: 'StorageEventsFinality',
locked: true,
lockedEnd: end,
started: now
});

job.save(function(err, job) {
if (err) {
return done(err);
}

expect(job.name).to.equal('StorageEventsFinality');
expect(job.locked).to.equal(true);
expect(job.lockedEnd).to.equal(end);
expect(job.started).to.equal(now);
done();
});
});
});

describe('#lock', function () {

it('should get lock without document', function(done) {

Cron.lock('SingletonOne', 1000, function(err) {
if (err) {
return done(err);
}
done();
});

});

it('should not get lock with existing locked document', function(done) {

Cron.lock('SingletonTwo', 10000, function(err, locked) {
if (err) {
return done(err);
}
expect(locked).to.equal(true);

Cron.lock('SingletonTwo', 10000, function(err, locked) {
if (err) {
return done(err);
}
expect(locked).to.equal(false);
done();
});
});

});

it('should get lock with expired locked document', function(done) {
const now = new Date();
const clock = sandbox.useFakeTimers();
clock.tick(now.getTime());
const expires = 10000;

Cron.lock('SingletonThree', expires, function(err, locked, res) {
if (err) {
return done(err);
}
expect(locked).to.equal(true);
expect(res);
clock.tick(expires);

Cron.lock('SingletonThree', expires, function(err, locked, res) {
if (err) {
return done(err);
}
expect(locked).to.equal(true);
expect(res);
done();
});
});
});

});

});
23 changes: 14 additions & 9 deletions test/storage-event.unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,27 @@ describe('Storage/models/Storage-Event', function() {

it('should create storage event with default props', function(done) {
var newStorageEvent = new StorageEvent({
bucket: mongoose.Types.ObjectId(),
bucketEntry: mongoose.Types.ObjectId(),
user: 'user@gmail.com',
downloadBandwidth: 0,
storage: 1000000,
farmer: 'c5857d99d3ff951701093b75fba94e1c82877f9b',
client: 'user@gmail.com'
});

newStorageEvent.save(function(err, storEvent) {
newStorageEvent.save(function(err, storeEvent) {
if (err) {
return done(err);
}
let ObjectIdType = mongoose.Types.ObjectId;
expect(err).to.not.be.an.instanceOf(Error);
expect(storEvent.bucket).to.be.an.instanceOf(ObjectIdType);
expect(storEvent.bucketEntry).to.be.an.instanceOf(ObjectIdType);
expect(storEvent.user).to.be.a('string');
expect(storEvent.timestamp).to.be.an.instanceOf(Date);
expect(storEvent.downloadBandwidth).to.be.a('number');
expect(storEvent.storage).to.be.a('number');
expect(storeEvent._id).to.be.instanceOf(ObjectIdType);
expect(storeEvent.user).to.be.a('string');
expect(storeEvent.timestamp).to.be.an.instanceOf(Date);
expect(storeEvent.downloadBandwidth).to.be.a('number');
expect(storeEvent.storage).to.be.a('number');
expect(storeEvent.farmer)
.to.equal('c5857d99d3ff951701093b75fba94e1c82877f9b');
expect(storeEvent.client).to.equal('user@gmail.com');
done();
});
});
Expand Down

0 comments on commit 3422c6d

Please sign in to comment.