Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom middleware to mutate input does not work #6743

Open
3 of 4 tasks
alfaproject opened this issue Dec 17, 2024 · 5 comments
Open
3 of 4 tasks

Custom middleware to mutate input does not work #6743

alfaproject opened this issue Dec 17, 2024 · 5 comments
Assignees
Labels
bug This issue is a bug. p2 This is a standard priority issue

Comments

@alfaproject
Copy link

Checkboxes for prior research

Describe the bug

I did a custom DynamoDB client middleware to log used capacity units when a specific environment variable is set by mutating the input to the operations to include the ReturnConsumedCapacity when said env variable is configured, but the input that is mutated is ignored completely and only the original command input is serialized in the request

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

@aws-sdk/[email protected]

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v20.11.0

Reproduction Steps

import { ConsumedCapacity, ServiceInputTypes, ServiceOutputTypes } from '@aws-sdk/client-dynamodb';
import { InitializeMiddleware, Pluggable } from '@aws-sdk/types';
import { RegionResolvedConfig } from '@smithy/config-resolver';
import { logInfo } from '@tma/core-log';
import { getEnvNumber } from '@tma/node-env';

function createLogConsumedCapacityMiddleware(
  minConsumedCapacityUnits: number,
): InitializeMiddleware<ServiceInputTypes, ServiceOutputTypes> {
  return next => async args => {
    args.input = {
      ...args.input,
      ReturnConsumedCapacity: 'TOTAL',
    };

    const result = await next(args);

    const output = result.output as { ConsumedCapacity?: ConsumedCapacity | ConsumedCapacity[] };

    const consumedCapacities = output.ConsumedCapacity
      ? Array.isArray(output.ConsumedCapacity)
        ? output.ConsumedCapacity
        : [output.ConsumedCapacity]
      : [];

    if (consumedCapacities.some(consumedCapacity => (consumedCapacity.CapacityUnits ?? 0) >= minConsumedCapacityUnits)) {
      logInfo('ConsumedCapacity', {
        consumedCapacity: output.ConsumedCapacity,
        input: args.input,
      });
    }

    return result;
  };
}

export function createLogConsumedCapacityPlugin(_config: RegionResolvedConfig): Pluggable<ServiceInputTypes, ServiceOutputTypes> {
  return {
    applyToStack: stack => {
      const LOG_CONSUMED_CAPACITY = getEnvNumber('DYNAMODB_LOG_CONSUMED_CAPACITY', 0);
      if (LOG_CONSUMED_CAPACITY) {
        stack.add(createLogConsumedCapacityMiddleware(LOG_CONSUMED_CAPACITY), {
          name: 'logConsumedCapacityMiddleware',
          step: 'initialize',
        });
      }
    },
  };
}

Observed Behavior

ReturnConsumedCapacity is ignored in the new input

Expected Behavior

ReturnConsumedCapacity should not be ignored and the DynamoDB operations should return the CapacityUnits used

Possible Solution

No response

Additional Information/Context

No response

@alfaproject alfaproject added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Dec 17, 2024
@aBurmeseDev aBurmeseDev self-assigned this Dec 23, 2024
@aBurmeseDev
Copy link
Member

Hi @alfaproject - thanks for reaching out.

Could you try this simpler version of code modifying ReturnConsumedCapacity in the middleware? It's working as expected for me.

import { DynamoDB } from "@aws-sdk/client-dynamodb";

const ddb = new DynamoDB();

ddb.middlewareStack.add(
  (next) => (args) => {
    args.input = {
      ...args.input,
      ReturnConsumedCapacity: "TOTAL",
    };

    return next(args);
  },
  {
    name: "logConsumedCapacityMiddleware",
    step: "initialize",
    override: true,
  }
);

await ddb.putItem({
  TableName: "test",
  Item: {
    id: {
      S: "1",
    },
    value: {
      S: "hello",
    },
  },
});

const item = await ddb.getItem({
  TableName: "test",
  Key: {
    id: {
      S: "1",
    },
  },
});

console.log(item);

@aBurmeseDev aBurmeseDev added response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. p2 This is a standard priority issue and removed needs-triage This issue or PR still needs to be triaged. labels Jan 3, 2025
@alfaproject
Copy link
Author

alfaproject commented Jan 4, 2025

Hello, thank you for your support, but that doesn't work either.

I suspect the problem is from DynamoDBDocumentClient doing something to the middleware stack and getting rid of or overriding the input from my custom middleware, because I'm using this client using DocumentClient like so:

// DocumentClient factory which is the one we're really using in our application
export function dynamoDbDocumentClient() {
  const ddb = new DynamoDBClient();
  ddb.middlewareStack.use(createLogConsumedCapacityPlugin(ddb.config));

  return DynamoDBDocumentClient.from(ddb);
}

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Jan 5, 2025
@aBurmeseDev
Copy link
Member

because I'm using this client using DocumentClient like so:

I may have misunderstood your workflow. In the code provided in the issue description, I saw that @aws-sdk/client-dynamodb was being imported, and it appeared that ReturnConsumedCapacity was not being used. However, now you mentioned @aws-sdk/lib-dynamodb. Could you please clarify which library you're using and provide more context about your setup? I'd be happy to assist further once I have a better understanding.

@aBurmeseDev aBurmeseDev added the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Jan 7, 2025
@alfaproject
Copy link
Author

I have pasted the code above in my comment. Is it not clear? I'm adding the middleware to DynamoDBClient but I use that client for DynamoDBDocumentClient because that's how we need to use the DynamoDBDocumentClient, right? I'm guessing that DynamoDBDocumentClient is doing something to the middleware stack of DynamoDBClient?

My middleware has nothing specific to DynamoDBDocumentClient but somehow it's not getting respected when using it that way which is the problem I guess

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. label Jan 9, 2025
@alfaproject
Copy link
Author

While waiting for your feedback, I have tried to add the middleware to the DynamoDBDocumentClient directly but it doesn't work either:

// DocumentClient factory which is the one we're really using in our application
export function dynamoDbDocumentClient() {
  const ddb = new DynamoDBClient();

  const ddbDocumentClient = DynamoDBDocumentClient.from(ddb);
  ddbDocumentClient.middlewareStack.use(createLogConsumedCapacityPlugin(ddbDocumentClient.config));
  return ddbDocumentClient;
}

ConsumedCapacity is also not returned that way. The middleware code is the same from my first post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. p2 This is a standard priority issue
Projects
None yet
Development

No branches or pull requests

2 participants