electrodb icon indicating copy to clipboard operation
electrodb copied to clipboard

Create in TransactionWrite does not return new entity

Open Talljoe opened this issue 1 year ago • 3 comments

Describe the bug I ported some code that uses create to the new Transaction API and the result from go does not include the same information. I would expect my created entity (with all the defaults and sets run) to be returned upon success.

ElectroDB Version 2.5.0

DynamoDB Client Version 3.296.0

ElectroDB Playground Link Link

Code Example

// Without Transaction
    const item = await DbService.entities.myEntity
      .create({
        name,
        accountId: accountId,
        startTime: startTime.toISOString(),
      })
      .go();
    return item.data; // Has data

// With Transaction
    const { name, accountId, startTime } = input;
    const result = await DbService.transaction
      .write(({ myEntity }) => [
        myEntity
          .create({
            name,
            accountId: accountId,
            startTime: startTime.toISOString(),
          })
          .commit(),
      ])
      .go();
    if (result.canceled || result.data[0].rejected) {
      throw new Error(result.data[0].code);
    }
    return result.data[0].item!; // Is null!

Expected behavior In a transaction context, data[n].item should contain the same content as item.data in a non-transaction context.

Errors

If applicable, paste the errors you received

Additional context Logging:

Without Transaction:

[
  {
    "type": "query",
    "method": "put",
    "params": {
      "Item": {
        "accountId": "Bob",
        "entityId": "01GWFEVQ1K20V3YQR0BKR44TBX",
        "name": "A new two!",
        "startTime": "2023-05-01T12:42:45.000Z",
        "createdAt": "2023-03-26T17:18:37.623Z",
        "updatedAt": "2023-03-26T17:18:37.623Z",
        "pk": "$myentity#accountid_bob#entityid_01gwfevq1k20v3yqr0bkr44tbx",
        "sk": "$viewers#myentity_1",
        "gsi1pk": "$myentity#accountid_bob",
        "gsi1sk": "$events#myentity_1#starttime_2023-05-01t12:42:45.000z#entityid_01gwfevq1k20v3yqr0bkr44tbx",
        "__edb_e__": "MyEntity",
        "__edb_v__": "1"
      },
      "TableName": "table-name",
      "ConditionExpression": "attribute_not_exists(#pk) AND attribute_not_exists(#sk)",
      "ExpressionAttributeNames": {
        "#pk": "pk",
        "#sk": "sk"
      }
    },
    "config": {
      "includeKeys": false,
      "originalErr": false,
      "raw": false,
      "params": {},
      "page": {},
      "lastEvaluatedKeyRaw": false,
      "pager": "named",
      "unprocessed": "item",
      "response": "default",
      "cursor": null,
      "data": "attributes",
      "ignoreOwnership": false,
      "_isPagination": false,
      "_isCollectionQuery": false,
      "pages": 1,
      "listeners": [],
      "preserveBatchOrder": false,
      "attributes": [],
      "terminalOperation": "go",
      "formatCursor": {}
    }
  }

  {
    "type": "results",
    "method": "put",
    "config": {
      "includeKeys": false,
      "originalErr": false,
      "raw": false,
      "params": {},
      "page": {},
      "lastEvaluatedKeyRaw": false,
      "pager": "named",
      "unprocessed": "item",
      "response": "default",
      "cursor": null,
      "data": "attributes",
      "ignoreOwnership": false,
      "_isPagination": false,
      "_isCollectionQuery": false,
      "pages": 1,
      "listeners": [],
      "preserveBatchOrder": false,
      "attributes": [],
      "terminalOperation": "go",
      "formatCursor": {}
    },
    "success": true,
    "results": {
      "$metadata": {
        "httpStatusCode": 200,
        "requestId": "EVN328S7DA8374BM0SHTISJKK3VV4KQNSO5AEMVJF66Q9ASUAAJG",
        "attempts": 1,
        "totalRetryDelay": 0
      }
    }
  }

With Transaction:

  {
    "type": "query",
    "method": "transactWrite",
    "params": {
      "TransactItems": [
        {
          "Put": {
            "Item": {
              "accountId": "Bob",
              "entityId": "01GWFEN6ER22P298NWMTW01Y18",
              "name": "A new one!",
              "startTime": "2023-05-01T12:42:45.000Z",
              "createdAt": "2023-03-26T17:15:04.027Z",
              "updatedAt": "2023-03-26T17:15:04.027Z",
              "pk": "$myentity#accountid_bob#entityid_01gwfen6er22p298nwmtw01y18",
              "sk": "$viewers#myentity_1",
              "gsi1pk": "$myentity#accountid_bob",
              "gsi1sk": "$events#myentity_1#starttime_2023-05-01t12:42:45.000z#entityid_01gwfen6er22p298nwmtw01y18",
              "__edb_e__": "MyEntity",
              "__edb_v__": "1"
            },
            "TableName": "table-name",
            "ConditionExpression": "attribute_not_exists(#pk) AND attribute_not_exists(#sk)",
            "ExpressionAttributeNames": {
              "#pk": "pk",
              "#sk": "sk"
            }
          }
        }
      ]
    },
    "config": {}
  }

  {
    "type": "results",
    "method": "transactWrite",
    "config": {},
    "success": true,
    "results": {
      "$metadata": {
        "httpStatusCode": 200,
        "requestId": "VO50L346VSIUBOLSVS6NH1MCUNVV4KQNSO5AEMVJF66Q9ASUAAJG",
        "attempts": 1,
        "totalRetryDelay": 0
      }
    }
  }

Talljoe avatar Mar 26 '23 17:03 Talljoe

Hi @Talljoe 👋

I agree in this case it would be nice to receive back the item you created, similar to the put and create methods on an entity. I'll look into why this is not happening and report back 👍

tywalch avatar Apr 08 '23 19:04 tywalch

I’m still relatively new to DynamoDB, so it is entirely possible I have missed something, but it seems that TransactWriteItems doesn’t support ReturnValues or any equivalent — except in the case of condition failure.

Maybe the types could be improved so that data[n].item is only present when the commit was rejected?

That said, it would be nice to get at default values that ElectroDB generates as part of a successful put or create. Maybe something like a data[n].committedItem value could be added to distinguish it from something that was returned from DynamoDB?

limulus avatar May 14 '23 15:05 limulus