dynamoose: [BUG] No error thrown for invalid condition
Summary:
Dynamoose does not throw/log an error when we create an invalid Dynamoose#Condition, using the DynamoDB condition syntax. This causes silent logic bugs!
Code sample:
Schema
const definition = new dynamoose.Schema(
{
id: {
type: String,
required: true,
},
value: {
type: String,
required: true,
},
randomNumber: {
type: Number,
required: true,
},
},
{
/**
* Let Dynamoose manage the `createdAt` and `updatedAt` timestamps,
* Unix epoch in seconds (not milliseconds)
*/
timestamps: true,
},
);
Model
const tableName = 'dipack_dynamoose_bug_repro';
const Model = dynamoose.model(tableName, definition, { create: true });
General
// ========== ALL CODE HERE INCLUDING SCHEMA AND MODEL =============
const dynamoose = require('dynamoose');
const ddb = new dynamoose.aws.sdk.DynamoDB({
region: 'eu-west-1',
version: 'latest',
});
dynamoose.aws.ddb.set(ddb);
const tableName = 'dipack_dynamoose_bug_repro';
const definition = new dynamoose.Schema(
{
id: {
type: String,
required: true,
},
value: {
type: String,
required: true,
},
randomNumber: {
type: Number,
required: true,
},
},
{
/**
* Let Dynamoose manage the `createdAt` and `updatedAt` timestamps,
* Unix epoch in seconds (not milliseconds)
*/
timestamps: true,
},
);
const DELETION_THRESHOLD_MS = (1000 * 60);
const now = Date.now();
const buggyQuery = new dynamoose.Condition({
FilterExpression: '#createdAtCol <= :createdAtValue OR #updatedAtCol <= :updatedAtValue',
ExpressionAttributeValues: {
':createdAtValue': {
N: now - DELETION_THRESHOLD_MS,
},
':updatedAtValue': {
N: now - DELETION_THRESHOLD_MS,
},
},
ExpressionAttributeNames: {
'#createdAtCol': 'createdAt',
'#updatedAtCol': 'updatedAt',
},
});
const workingQueryDyn = new dynamoose.Condition().where('createdAt').le(now - DELETION_THRESHOLD_MS).or().where('updatedAt').le(now - DELETION_THRESHOLD_MS);
(async () => {
const Model = dynamoose.model(tableName, definition, { create: true });
const existingRows = await Model.scan().exec();
console.log(`Found ${existingRows.length} rows.`);
const newRows = await Promise.all(
new Array(5).fill(0).map(async (_, idx) => {
const id = Math.floor(Math.random() * 10 ** 10);
const row = await Model.create({
id: String(id),
value: `${id}-${idx}`,
randomNumber: Math.random(),
});
return row;
})
).catch(err => console.error('Error while creating new rows', err));
console.log(`Created ${newRows.length} new rows.`);
const filteredRows = await Model.scan(buggyQuery).exec();
console.log(`Filtered ${filteredRows.length} rows using DynamoDB condition API`);
const allRows = await Model.scan().exec();
if (allRows.every(row => filteredRows.find(fRow => fRow.id === row.id) !== undefined)) {
console.warn('No rows were filtered!');
}
const filteredRowsDyn = await Model.scan(workingQueryDyn).exec();
console.log(`Filtered ${filteredRowsDyn.length} rows using Dynamoose condition API`);
if (allRows.every(row => filteredRowsDyn.find(fRow => fRow.id === row.id) !== undefined)) {
console.warn('No rows were filtered, using the Dynamoose API too!');
}
console.log('DynamoDB API condition object', buggyQuery.requestObject());
console.log('Dynamoose API condition object', workingQueryDyn.requestObject());
})();
Current output and behavior (including stack trace):
The DynamoDB based Condition is currently shown as an empty object.
Found 105 rows.
Created 5 new rows.
Filtered 110 rows using DynamoDB condition API
Filtered 100 rows using Dynamoose condition API
DynamoDB API condition object {}
Dynamoose API condition object {
ConditionExpression: '#a0 <= :v0 OR #a1 <= :v1',
ExpressionAttributeNames: { '#a0': 'createdAt', '#a1': 'updatedAt' },
ExpressionAttributeValues: { ':v0': { N: '1640063029486' }, ':v1': { N: '1640063029486' } }
}
Expected output and behavior:
Expect the condition objects built using the DynamoDB syntax, and the Dynamoose API to be the same. If the condition generated is invalid, then we should throw an error.
Environment:
Operating System: MacOS
Operating System Version: 12.1 Monterey
Node.js version (node -v): 14.17.3
NPM version: (npm -v): 6.14.13
Dynamoose version: 2.8.3
Other information (if applicable):
Other:
- I have read through the Dynamoose documentation before posting this issue
- I have searched through the GitHub issues (including closed issues) and pull requests to ensure this issue has not already been raised before
- I have searched the internet and Stack Overflow to ensure this issue hasn’t been raised or answered before
- I have tested the code provided and am confident it doesn’t work as intended
- I have filled out all fields above
- I am running the latest version of Dynamoose
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 16 (8 by maintainers)
Commits related to this issue
- Fixing bug where nested raw conditions wouldn't work closes #1323 — committed to dynamoose/dynamoose by fishcharlie 3 years ago
@fishcharlie It worked! 🥳
@dipack95 Forgot to push 😆. Check again now.
@dipack95 Please do me a favor and dig into this a bit further yourself. I have limited resources and insight into your code and items in your table.
Maybe try running “dynamoose.logger.providers.set([console]);” to see what that outputs.
And please work on trying to create an MCVE.
As far as I can tell everything is working fine. I need more context here about what specifically isn’t working as opposed to just a bunch of code (most of which isn’t relevant to this issue).