Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update batchPut to work with timestamps #449

Merged
merged 6 commits into from
Oct 18, 2018

Conversation

dolsem
Copy link
Contributor

@dolsem dolsem commented Oct 17, 2018

Summary:

Second take on #447.

Currently batchPut fails with error Cannot read property 'updateTimestamps' of undefined if a model uses timestamps. The error results from this line, because toDynamo is called without options here.

This PR fixes the issue and adds two options to batchPut: updateTimestamps (defaults to false, because currently batchPut does not update timestamps), and updateExpires (also defaults to false).

Type (select 1):

  • Bug fix
  • Feature implementation
  • Documentation improvement
  • Testing improvement
  • Test added to report bug (GitHub issue #--- @---)
  • Something not listed here

Is this a breaking change? (select 1):

  • 🚨 YES 🚨
  • No
  • I'm not sure

Is this ready to be merged into Dynamoose? (select 1):

  • Yes
  • No

Are all the tests currently passing on this PR? (select 1):

  • Yes
  • No

Other:

  • I have searched through the GitHub pull requests to ensure this PR has not already been submitted
  • I have updated the Dynamoose documentation (if required) given the changes I made
  • I have added/updated the Dynamoose test cases (if required) given the changes I made
  • I have run npm test from the root of the project directory to ensure all tests continue to pass
  • I agree that all changes made in this pull request may be distributed and are made available in accordance with the Dynamoose license
  • All of my commits and commit messages are detailed, explain what changes were made, and are easy to follow and understand
  • I have confirmed that all my code changes are indented properly using 2 spaces
  • I have filled out all fields above

@coveralls
Copy link

Pull Request Test Coverage Report for Build 685

  • 5 of 5 (100.0%) changed or added relevant lines in 1 file are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.07%) to 85.156%

Files with Coverage Reduction New Missed Lines %
lib/Table.js 2 77.93%
Totals Coverage Status
Change from base Build 682: 0.07%
Covered Lines: 1880
Relevant Lines: 2137

💛 - Coveralls

1 similar comment
@coveralls
Copy link

Pull Request Test Coverage Report for Build 685

  • 5 of 5 (100.0%) changed or added relevant lines in 1 file are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.07%) to 85.156%

Files with Coverage Reduction New Missed Lines %
lib/Table.js 2 77.93%
Totals Coverage Status
Change from base Build 682: 0.07%
Covered Lines: 1880
Relevant Lines: 2137

💛 - Coveralls

@coveralls
Copy link

coveralls commented Oct 17, 2018

Pull Request Test Coverage Report for Build 689

  • 1 of 1 (100.0%) changed or added relevant line in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.08%) to 85.168%

Totals Coverage Status
Change from base Build 682: 0.08%
Covered Lines: 1876
Relevant Lines: 2133

💛 - Coveralls

Copy link
Member

@fishcharlie fishcharlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really good. Just a few suggestions.


**updateTimestamps**: boolean

Should update the `updatedAt` timestamp if exists. Defaults to true.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be Defaults to false for the documentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's right. Oops!

lib/Model.js Outdated
if (options.updateTimestamps === true) {
toDynamoOptions.updateTimestamps = true;
}
if (options.updateExpires === true) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing these two if statements why not do something like the following?

let toDynamoOptions = {
  updateTimestamps: options.updateTimestamps || false,
  updateExpires: options.updateExpires || false
};

We might even be able to reduce it to something like the following since it'd be falsey if it doesn't exist.

let toDynamoOptions = {
  updateTimestamps: options.updateTimestamps,
  updateExpires: options.updateExpires
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I personally like this more (your first version). I was trying to copy the existing code style as much as possible. But since you suggested it yourself, I'll definitely change it. Not a fan of the second version, because it's slightly less telling and not as safe. So I'll go with the first one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dolsem I'd like to refactor a lot of that code and fix up a lot of things to use more things like the versions I had above. It'd be a massive project but at some point I'd like to go through and clean up a lot of the Dynamoose code to make it more clean.

Not sure when that will happen tho. Until then I fully support new code using those type of clean coding practices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, got you.

test/Model.js Outdated
should.exist(result3);
result3.length.should.eql(cats.length);

result3.forEach(cat => cat.myLittleUpdatedAt.should.not.eql(timestamps[cat.id]));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking we should set this to check to ensure the new updated at is greater than the old value. Just to make this test more thorough.

test/Model.js Outdated

result3.forEach((cat) => {
cat.array.length.should.eql(2);
cat.expires.should.not.eql(originalExpires[cat.id]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here, this should probably check to see if it's greater than the old value.

test/Model.js Outdated
var timestamps = {};
for (var i=0 ; i<10 ; ++i) {
cats[i].name = 'John_'+i;
Object.assign(timestamps, { [cats[i].id]: new Date(cats[i].myLittleUpdatedAt) });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a huge fan of Object.assign if we can avoid it. Is there a better method for this? Something like the following maybe?

timestamps[cats[i].id] = new Date(cats[i].myLittleUpdatedAt);

To me that is much simpler code and easier to understand. I don't think Object.assign makes a lot of sense in this context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

test/Model.js Outdated
var timestamps = {};
for (var i=0 ; i<10 ; ++i) {
cats[i].name = 'John_'+i;
Object.assign(timestamps, { [cats[i].id]: new Date(cats[i].myLittleUpdatedAt) });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here. Something like the following maybe?

timestamps[cats[i].id] = new Date(cats[i].myLittleUpdatedAt);

test/Model.js Outdated
var timestamps = {};
for (var i=0 ; i<10 ; ++i) {
cats[i].name = 'John_'+i;
Object.assign(timestamps, { [cats[i].id]: new Date(cats[i].myLittleUpdatedAt) });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here. Something like the following maybe?

timestamps[cats[i].id] = new Date(cats[i].myLittleUpdatedAt);

test/Model.js Outdated
result3.length.should.eql(cats.length);

originalExpires = result3.reduce(
(acc, cat) => Object.assign(acc, { [cat.id]: cat.expires }),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.assign makes sense to me here. Here is another option, but totally up to you if you want to use this or not. I think your code is completely fine here, but just another option to keep it consistent in terms of not using Object.assign.

Change the code above to:

var originalExpires = {};

Then here do:

result3.forEach(cat => {
  acc[cat.id] = cat.expires;
});

You could also make that a for loop since it seems like you are using that a lot throughout these tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think it's always best to stick to either good old procedural style or functional, not combining the two. I lean towards functional with JavaScript, but I was reusing some of the code from other tests in the same file, I didn't want my tests to look radically different from everything around. I guess I'll make things more consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dolsem If Object.assign is used a lot throughout the tests then that is fine. I'm not sure what is currently being used for these cases.

@dolsem
Copy link
Contributor Author

dolsem commented Oct 18, 2018

I've just made the updates you requested, as well as a few other updates to code style. Let me know if there's anything else.

Copy link
Member

@fishcharlie fishcharlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more thing

timestamps[id] = new Date(myLittleUpdatedAt);
});

await new Promise(resolve => setTimeout(resolve, 1000));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized one more thing I forgot to mention. Why not make this something much shorter? Like 5 or even 1? Is there a specific reason why we have to wait a full second here? Waiting just a few milliseconds should ensure that the timestamps are later than the original value, correct?

If we decide to edit it we have to make sure we do it throughout these new tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I tried making it shorter, and the tests would sometimes fail. Seems like when timestamps get updated milliseconds get stripped away either on the original objects after they saved or on the results of batchGet, not sure which one right now. I didn't have time to investigate this, so I don't know if this is the result of floor, ceiling, or round, so to be safe I made it wait a full second. This made the tests deterministic, no chance of failure anymore. I might be mistaken, but I think the same timeout is used for other tests around timestamps in the test suit too.

Copy link
Member

@fishcharlie fishcharlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fishcharlie
Copy link
Member

@dolsem Thanks for your hard work on this! I'll get this merged in soon!!

@fishcharlie fishcharlie mentioned this pull request Oct 18, 2018
@fishcharlie fishcharlie merged commit 43773c3 into dynamoose:master Oct 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants