8000 feat(http): add IdempotencyKey in header if present by paul-nicolas · Pull Request #70 · formancehq/webhooks · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(http): add IdempotencyKey in header if present #70

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

Merged
merged 1 commit into from
Jan 31, 2025

Conversation

paul-nicolas
Copy link
Contributor

No description provided.

Copy link
coderabbitai bot commented Jan 31, 2025

Walkthrough

The pull request introduces a new idempotency key feature across multiple files in the webhooks system. The changes modify the MakeAttempt function signature to include an additional idempotencyKey parameter, enabling more precise control over request uniqueness. This modification impacts several components, including the server test handler, worker processing, and retry mechanisms, allowing for more robust handling of webhook attempts and preventing potential duplicate request processing.

Changes

File Change Summary
pkg/attempt.go Updated MakeAttempt function signature to include idempotencyKey parameter; added conditional header setting for Idempotency-Key.
pkg/server/test.go Modified testOneConfigHandle to pass static idempotency key "ik" to MakeAttempt.
pkg/worker/module.go Updated processMessages to include ev.IdempotencyKey when calling MakeAttempt.
pkg/worker/worker.go Added JSON unmarshalling for event messages in attemptRetries; imported new packages for event handling.

Sequence Diagram

sequenceDiagram
    participant Client
    participant WebhookSystem
    participant TargetService

    Client->>WebhookSystem: Send Webhook Request
    WebhookSystem->>WebhookSystem: Generate Idempotency Key
    WebhookSystem->>TargetService: Make Attempt with Idempotency Key
    alt First Attempt
        TargetService-->>WebhookSystem: Success
    else Duplicate Attempt
        TargetService-->>WebhookSystem: Ignore/Deduplicate
    end
Loading

Poem

🐰 A Rabbit's Webhook Rhyme 🌈

With idempotency, we dance and prance,
No duplicate requests shall get a chance!
Keys unique, our system stays clean,
Preventing chaos, a webhook's dream!
Hop, hop, hooray for retry's might! 🚀

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@paul-nicolas paul-nicolas marked this pull request as ready for review January 31, 2025 12:39
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
pkg/attempt.go (1)

38-38: Add documentation for the idempotencyKey parameter.

Consider adding a comment explaining the purpose and format requirements of the idempotencyKey parameter.

+// MakeAttempt creates a new webhook attempt with the given configuration.
+// If idempotencyKey is not empty, it will be added as a header to ensure
+// idempotent request processing on the server side.
 func MakeAttempt(ctx context.Context, httpClient *http.Client, retryPolicy BackoffPolicy, id, webhookID string, attemptNb int, cfg Config, idempotencyKey string, payload []byte, isTest bool) (Attempt, error) {
pkg/worker/worker.go (1)

108-113: Improve error message for JSON unmarshalling.

The error message could be more descriptive to help with debugging.

 var ev publish.EventMessage
 err = json.Unmarshal([]byte(atts[0].Payload), &ev)
 if err != nil {
-    errChan <- errors.Wrap(err, "json.Unmarshal")
+    errChan <- errors.Wrapf(err, "failed to unmarshal payload for webhookID: %s, attempt: %s", webhookID, atts[0].ID)
     continue
 }
pkg/worker/module.go (1)

133-137: Improve error handling for JSON marshalling.

The error handling could be more descriptive and include context about the event being processed.

 data, err := json.Marshal(ev)
 if err != nil {
-    logging.FromContext(ctx).Error(err)
+    logging.FromContext(ctx).Errorf("failed to marshal event message of type %s: %v", ev.Type, err)
     return
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 023d615 and 9c6f229.

📒 Files selected for processing (4)
  • pkg/attempt.go (2 hunks)
  • pkg/server/test.go (1 hunks)
  • pkg/worker/module.go (1 hunks)
  • pkg/worker/worker.go (2 hunks)
🔇 Additional comments (2)
pkg/attempt.go (1)

57-59: Consider validating the idempotency key format.

The idempotency key is added to the header without validation. Consider adding basic validation to ensure it meets any format requirements.

pkg/worker/worker.go (1)

117-117: Consider handling potential nil idempotency key.

The code directly uses ev.IdempotencyKey without checking if it's nil or empty. Consider adding a check to handle this case gracefully.

@@ -27,7 +27,7 @@ func (h *serverHandler) testOneConfigHandle(w http.ResponseWriter, r *http.Reque
logging.FromContext(r.Context()).Debugf("GET %s/%s%s", PathConfigs, id, PathTest)
retryPolicy := backoff.NewNoRetry()
attempt, err := webhooks.MakeAttempt(r.Context(), h.httpClient, retryPolicy, uuid.NewString(),
uuid.NewString(), 0, cfgs[0], []byte(`{"data":"test"}`), true)
uuid.NewString(), 0, cfgs[0], "ik", []byte(`{"data":"test"}`), true)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

🛠️ Refactor suggestion

Additional test cases needed for idempotency key handling

Current implementation supports various idempotency key scenarios, but test coverage is limited to a single basic case. Based on the codebase analysis:

  • Add test case with empty idempotency key in pkg/server/test.go to verify the conditional header setting
  • Add test cases with different formats (UUID, timestamp-based, custom formats) to ensure proper handling
  • Add test case with a long idempotency key to verify there are no length-related issues
  • Consider testing header presence/absence based on the key value
🔗 Analysis chain

Improve test coverage for idempotency key scenarios.

The test uses a hard-coded "ik" value for the idempotency key. Consider adding test cases for:

  • Empty idempotency key
  • Different idempotency key formats
  • Very long idempotency keys
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing test cases related to idempotency key
rg -A 5 'test.*[Ii]dempotency.*Key|idempotencyKey.*test'

Length of output: 58


Script:

#!/bin/bash
# Search for "ik" usage in test files and the test function context
rg -l '\.go$' | xargs rg -B 5 -A 5 '"ik"'

# Search for idempotency-related code
rg -l '\.go$' | xargs rg -B 2 -A 2 '[Ii]dempotency'

Length of output: 2307

Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/worker/worker.go (1)

108-113: Enhance error handling for better debugging.

While the error handling is correct, consider adding logging and more context to the error message.

 var ev publish.EventMessage
 err = json.Unmarshal([]byte(atts[0].Payload), &ev)
 if err != nil {
-    errChan <- errors.Wrap(err, "json.Unmarshal")
+    logging.FromContext(ctx).WithError(err).Error("Failed to unmarshal event message")
+    errChan <- errors.Wrapf(err, "failed to unmarshal payload for webhookID: %s", webhookID)
     continue
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c6f229 and b6f691a.

📒 Files selected for processing (4)
  • pkg/attempt.go (2 hunks)
  • pkg/server/test.go (1 hunks)
  • pkg/worker/module.go (1 hunks)
  • pkg/worker/worker.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/server/test.go
  • pkg/worker/module.go
  • pkg/attempt.go
🔇 Additional comments (1)
pkg/worker/worker.go (1)

5-5: LGTM!

The new imports are necessary for handling the event message and extracting the idempotency key.

Also applies to: 11-11

newAttemptNb := atts[0].RetryAttempt + 1
attempt, err := webhooks.MakeAttempt(ctx, w.httpClient, w.retryPolicy, uuid.NewString(),
webhookID, newAttemptNb, atts[0].Config, []byte(atts[0].Payload), false)
webhookID, newAttemptNb, atts[0].Config, ev.IdempotencyKey, []byte(atts[0].Payload), false)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Validation of idempotency key is missing and should be added

The codebase shows consistent validation patterns for other important fields (endpoints, secrets, event types), but lacks any validation for idempotency keys. Consider adding validation in pkg/attempt.go where MakeAttempt is called to ensure:

  • The key is not empty
  • The key meets any length/format requirements
  • The key follows any business-specific constraints
🔗 Analysis chain

Consider validating the idempotency key.

The idempotency key is used directly from the event message without validation. Consider adding validation to ensure it meets any format or length requirements.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/b
8000
ash
# Description: Check if idempotency key validation exists in the codebase.

# Search for any existing validation of idempotency keys
rg -A 5 'IdempotencyKey.*valid|valid.*IdempotencyKey'

# Search for any constants or types defining idempotency key requirements
ast-grep --pattern 'const (
  $$$
  IdempotencyKey
  $$$
)'

Length of output: 117


Script:

#!/bin/bash
# Search for IdempotencyKey definition and usage
rg -A 5 "type.*IdempotencyKey|struct.*IdempotencyKey"

# Look for message/event validation patterns
rg -A 5 "func.*validate.*Event|func.*Validate.*Message"

# Find where IdempotencyKey is set/used
ast-grep --pattern 'IdempotencyKey = $_'

Length of output: 156


Script:

#!/bin/bash
# Look for method signatures containing IdempotencyKey
rg -A 5 "func.*\(.*[iI]dempotency.*\)"

# Search for string validation patterns
rg -A 5 "func.*validate.*string|len\(.*\)"

# Find event processing code
ast-grep --pattern 'func ($_) (ev Event) {
  $$$
}'

Length of output: 10914

@paul-nicolas paul-nicolas merged commit 76a4f5a into main Jan 31, 2025
7 checks passed
@paul-nicolas paul-nicolas deleted the feat/add-ik branch January 31, 2025 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0