tywalch/electrodb

`createdAt` is updated as `updatedAt` when I do an upsert on my Entity

clementmarcilhacy opened this issue ยท 2 comments

Describe the bug
I have an Entity with the attributes createdAt and updatedAt as defined in the electrodb playground:

createdAt: {
        type: "number",
        default: () => Date.now(),
        // cannot be modified after created
        readOnly: true
      },
updatedAt: {
        type: "number",
        // watch for changes to any attribute
        watch: "*",
        // set current timestamp when updated
        set: () => Date.now(),
        readOnly: true
      }

and I do an upsert on my Entity: const { data } = MyEntity.upsert(data).go() but both the createdAt and the updatedAt attributes are updated with the same Date.now() value.

It looks like the upsert method is always doing a PutItem, and then rewriting the object entirely in dynamodb.

According to the documentation, "Unlike the put method, however, upsert perform an update if that record already exists.".

ElectroDB Version
I am using version ^2.5.1

ElectroDB Playground Link

Entity/Service Definitions
Include your entity model (or a model that sufficiently recreates your issue) to help troubleshoot.

{
  model: {
    entity: "my_entity",
    service: "my_service",
    version: "my_version",
  },
  attributes: {
    prop1: {
      type: "string",
    },
    prop2: {
      type: "string",
    },
    createdAt: {
      type: "number",
      default: () => Date.now(),
      // cannot be modified after created
      readOnly: true,
    },
    updatedAt: {
      type: "number",
      // watch for changes to any attribute
      watch: "*",
      // set current timestamp when updated
      set: () => Date.now(),
      readOnly: true,
    },
  },
  indexes: {
    record: {
      pk: {
        field: "pk",
        composite: ["prop1"],
      },
      sk: {
        field: "sk",
        composite: ["prop2"],
      },
    },
  },
};

Expected behavior
createdAt not modified when doing an upsert for the second time.

Errors

Additional context

Actually, the problem seems to be with all readOnly attributes when doing an upsert (I did not test the other methods).

When doing an upsert, I expected the UpdateExpression to have a if_not_exists clause on the readOnly attributes.

I had to manually replace it in the the params sent to dynamodb:

const params = await MyEntity.upsert({prop1, prop2}).params();

params['UpdateExpression'] = params[
  'UpdateExpression'
].replace(
  '#createdAt = :createdAt_u0',
  '#createdAt = if_not_exists(#createdAt,:createdAt_u0)',
);

await MyEntity.upsert({prop1, prop2}).go({
  params,
});

Hi @clementmarcilhacy ๐Ÿ‘‹

This has been added to 2.7.0