get item by partition key returns error only inside lambda
orr-levinger opened this issue · 0 comments
Describe the bug
This bug happens to me only when running in a lambda. When running locally this doesnt happen.
here are my libs versions:
dynamo-easy version: 8.0.0-next.3
aws v3 dynamo version: 3.445.0
Node.js Version: v18.18.0
I have a model that has a string field called status:
import {
Model,
PartitionKey,
SortKey,
LSISortKey,
GSIPartitionKey,
GSISortKey,
Property,
fromDb as fromDBB,
PropertyMetadata,
metadataForModel,
Attributes,
ModelConstructor,
} from '@shiftcoders/dynamo-easy';
import { BaseDynamoModel } from '@models/base-dynamo-model';
import { MATCH_TABLE } from '@static/consts';
import { MatchGraphQLType, Quality, RejectReason } from '@type/Match';
import type { MatchStatus } from '@type/Match';
import { Avatar, Gender } from '@type/User';
import type { MapperForType, StringAttribute } from '@shiftcoders/dynamo-easy';
@Model({ tableName: MATCH_TABLE })
export class MatchModel extends BaseDynamoModel implements MatchGraphQLType {
static readonly byUniqueId = 'byUniqueId';
static readonly byMatchIdUserId = 'byMatchId-userId';
static readonly byUserIdStatus = 'byUserId-status';
static readonly byUserIdActive = 'byUserId-active';
static readonly byConversationId = 'byConversationId';
@GSIPartitionKey(MatchModel.byUniqueId)
id: string;
@PartitionKey()
@GSISortKey(MatchModel.byMatchIdUserId)
userId: string;
@SortKey()
@GSIPartitionKey(MatchModel.byMatchIdUserId)
matchId: string;
@LSISortKey(MatchModel.byUserIdStatus)
@Property({ mapper: statusMapper })
**status: MatchStatus;**
@LSISortKey(MatchModel.byUserIdActive)
active: 'true' | 'false';
}
export type MatchStatus =
| 'pending'
| 'invited'
| 'accepted'
| 'failure'
| 'success';
here is the DDB table definition:
MatchesTable:
DeletionPolicy: Delete
Type: "AWS::DynamoDB::Table"
Properties:
Tags:
- Key: env
Value: ${sls:stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: status
AttributeType: S
- AttributeName: userId
AttributeType: S
- AttributeName: matchId
AttributeType: S
- AttributeName: active
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: matchId
KeyType: RANGE
LocalSecondaryIndexes:
- IndexName: byUserId-status
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: status
KeyType: RANGE
Projection:
ProjectionType: ALL
- IndexName: byUserId-active
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: active
KeyType: RANGE
Projection:
ProjectionType: ALL
GlobalSecondaryIndexes:
- IndexName: byUniqueId
KeySchema:
- AttributeName: id
KeyType: HASH
Projection:
ProjectionType: ALL
- IndexName: byMatchId-userId
KeySchema:
- AttributeName: matchId
KeyType: HASH
- AttributeName: userId
KeyType: RANGE
Projection:
ProjectionType: ALL
BillingMode: PAY_PER_REQUEST
TableName: ${self:custom.base}-matches
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
here is my table item instance:
"userId": {
"S": "f43276be-3a2c-4888-b2b9-9ae23471094c"
},
"matchId": {
"S": "4913f5ad-198e-4fcd-b929-2f3e996ce6ce"
},
"active": {
"S": "true"
},
"id": {
"S": "f43276be-3a2c-4888-b2b9-9ae23471094c_4913f5ad-198e-4fcd-b929-2f3e996ce6ce"
},
"status": {
"S": "invited"
}
}
this is the query i run:
async getMatchById(id: string) {
return this.query().index(MatchModel.byUniqueId).wherePartitionKey(id).execSingle();
}
only when this code runs inside lambda i get the error:
{
"errorType": "Error",
"errorMessage": "could not resolve the dynamo db type for attribute value invited",
"stack": [
"Error: could not resolve the dynamo db type for attribute value invited",
" at typeOfFromDb (/opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/mapper/util.ts:231:9)",
" at fromDbOne (/opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/mapper/mapper.ts:291:64)",
" at /opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/mapper/mapper.ts:274:20",
" at Array.forEach ()",
" at fromDb (/opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/mapper/mapper.ts:244:44)",
" at Object.fromDb (/var/task/src/functions/events/webpack:/blind-chat-backend/src/models/match-model.ts:75:14)",
" at /opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/mapper/mapper.ts:268:50",
" at Array.forEach ()",
" at fromDb (/opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/mapper/mapper.ts:244:44)",
" at /opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/dynamo/request/read-many.request.ts:222:63",
" at Array.map ()",
" at ReadManyRequest.mapFromDb (/opt/nodejs/node_modules/@shiftcoders/dynamo-easy/src/dynamo/request/read-many.request.ts:222:43)",
" at processTicksAndRejections (node:internal/process/task_queues:95:5)",
" at Runtime.v [as handler] (/var/task/src/functions/events/webpack:/blind-chat-backend/src/functions/events/get-match.ts:16:3)"
]
}
when creating a property mapper:
export const statusMapper: MapperForType<string, StringAttribute> = {
fromDb: (attributeValue: any): any => {
console.log('fromDb orr', attributeValue);
return attributeValue.S;
},
toDb: (modelValue: any): any => {
console.log('toDb orr', modelValue);
try {
return modelValue;
} catch (e) {
console.log('error', e);
return modelValue;
}
},
};
that does nothing special just what dynamo-easy was supposed to do it works..
and prints:
fromDb orr { S: 'invited' }
also noticed the wrong mapper is chosen:
INFO dynamo.mapper.mapper (Object): map toDb {"item":"Conscientiousness"}