簡體   English   中英

DynamoDB JavaScript PutItemCommand 既沒有失敗也沒有工作

[英]DynamoDB JavaScript PutItemCommand is neither failing nor working

請注意:雖然這個問題提到了 AWS SAM,但它 100% 是一個 DynamoDB JavaScript SDK 問題的核心,任何有使用 AWS DynamoDB 客戶端/SDK 針對 DynamoDB 編寫 JavaScript Lambdas(或任何客戶端應用程序)經驗的人都可以回答。


因此,我使用 AWS SAM 預置了一個具有以下屬性的新 DynamoDB 表:

FeedbackDynamoDB:
  Type: AWS::DynamoDB::Table
  Properties:
    TableName: commentary
    AttributeDefinitions:
      - AttributeName: id
        AttributeType: S
    KeySchema:
      - AttributeName: id
        KeyType: HASH
    ProvisionedThroughput:
      ReadCapacityUnits: 5
      WriteCapacityUnits: 5
    StreamSpecification:
      StreamViewType: NEW_IMAGE

此配置成功創建了一個名為commentary的 DynamoDB 表。 但是,當我在 DynamoDB web 控制台中查看此表時,我注意到了一些事情:

  • 它有一個分區鍵 id(類型 S)
  • 它沒有排序鍵
  • 它沒有 (0) 個索引
  • 它的讀/寫容量模式為“5”

我不確定這是否會引起任何人的注意,但我想我會包括這些詳細信息,以防我配置不正確。

現在,我有一個 JavaScript (TypeScript) Lambda 實例化一個 DynamoDB 客戶端(使用 JavaScript SDK)並嘗試向該表添加記錄/項目:

// this code is in a file named app.ts:
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { User, allUsers } from './users';
import { Commentary } from './commentary';
import { PutItemCommand } from "@aws-sdk/client-dynamodb";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
    try {

        const ddbClient = new DynamoDBClient({ region: "us-east-1" });

        let status: number = 200;
        let responseBody: string = "\"message\": \"hello world\"";

        const { id, content, createdAt, providerId, receiverId } = JSON.parse(event.body);
        const commentary = new Commentary(id, content, createdAt, providerId, receiverId);
        console.log("deserialized this into commentary");
        console.log("and the deserialized commentary has content of: " + commentary.getContent());
        await provideCommentary(ddbClient, commentary);
        responseBody = "\"message\": \"received commentary -- check dynamoDb!\"";

        return {
            statusCode: status,
            body: responseBody
        };

    } catch (err) {
        console.log(err);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: err.stack,
            }),
        };
    }
};

const provideCommentary = async (ddbClient: DynamoDBClient, commentary: Commentary) => {

  const params = {
    TableName: "commentary",

    Item: {
      id: {
        S: commentary.getId()
      },
      content: {
        S: commentary.getContent()
      },
      createdAt: {
        S: commentary.getCreatedAt()
      },
      providerId: {
        N: commentary.getProviderId()
      },
      receiverId: {
        N: commentary.getReceiverId()
      }
    }

  };

  console.log("about to try to insert commentary into dynamo...");

  try {
    console.log("wait for it...")
    const rc = await ddbClient.send(new PutItemCommand(params));
    console.log("DDB response:", rc);
  } catch (err) {
    console.log("hmmm something awry. something....in the mist");
    console.log("Error", err.stack);
    throw err;
  }
};

其中commentary.ts是:

class Commentary {
  private id: string;
  private content: string;
  private createdAt: Date;
  private providerId: number;
  private receiverId: number;

  constructor(id: string, content: string, createdAt: Date, providerId: number, receiverId: number) {
    this.id = id;
    this.content = content;
    this.createdAt = createdAt;
    this.providerId = providerId;
    this.receiverId = receiverId;
  }

  public getId(): string {
    return this.id;
  }

  public getContent(): string {
    return this.content;
  }

  public getCreatedAt(): Date {
    return this.createdAt;
  }

  public getProviderId(): number {
    return this.providerId;
  }

  public getReceiverId(): number {
    return this.receiverId;
  }

}

export { Commentary };

當我使用此處理程序代碼更新 Lambda 並使用以下 curl 命中 Lambda 時(Lambda 由我可以通過 curl/http 命中的 API 網關 URL 調用):

curl -i --request POST 'https://<my-api-gateway>.execute-api.us-east-1.amazonaws.com/Stage/feedback' \
--header 'Content-Type: application/json' -d '{"id":"123","content":"test feedback","createdAt":"2022-12-02T08:45:26.261-05:00","providerId":457,"receiverId":789}'

我收到以下 HTTP 500 響應:

{"message":"SerializationException: NUMBER_VALUE cannot be converted to String\n

我是否向它傳遞了錯誤的請求正文(在 curl 中),或者我是否需要在app.ts和/或commentary.ts中進行一些調整?

有趣的是, DynamoDB API期望項目的數字字段為字符串。 例如:

"N": "123.45"

醫生說;

數字作為字符串通過網絡發送到 DynamoDB,以最大限度地提高跨語言和庫的兼容性。 但是,DynamoDB 將它們視為數學運算的數字類型屬性。

您是否嘗試過將數字參數作為字符串發送輸入,如下所示? (參見providerIdreceiverId

{
   "id":"123",
   "content":"test feedback",
   "createdAt":"2022-12-02T08:45:26.261-05:00",
   "providerId":"457",
   "receiverId":"789"
}

您可以在填充輸入Item時將這些 ID 轉換為字符串:

  providerId: {
    N: String(commentary.getProviderId())
  },
  receiverId: {
    N: String(commentary.getReceiverId())
  }

您也可以使用.toString()但如果未設置該字段( nullundefined ),您會收到錯誤消息。

嘗試使用 promise 來查看結果:

client.send(command).then(
  (data) => {
    // process data.
  },
  (error) => {
    // error handling.
  }
);

您的表設置似乎一切正常,我相信這是 Lambda 與 JS sdk 的異步問題。我猜 Lambda 沒有等待您的代碼並提前退出。 你能包括你完整的 lambda 代碼嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM