Skip to content

Conversation

@chrisgacsal
Copy link
Collaborator

@chrisgacsal chrisgacsal commented Apr 29, 2025

Overview

  • consilidate types
  • adopt tx creator

Summary by CodeRabbit

  • New Features

    • Introduced event delivery status management, including listing, retrieving, and updating delivery statuses for notification events.
    • Added a new database-backed notification repository adapter supporting transactional operations.
  • Refactor

    • Unified all notification rule and event type references to use a single event type, improving consistency across the system.
    • Replaced direct repository access with a new adapter interface for all notification-related operations.
    • Centralized and standardized transaction management for notification operations.
    • Refactored notification service methods to use the adapter interface and new transaction framework.
    • Removed legacy event delivery status types and validation from core event definitions.
  • Bug Fixes

    • Corrected type mismatches in rule and event handling.
    • Improved error aggregation and messaging for webhook delivery.
  • Tests

    • Updated tests to align with new event type usage and related changes.

@chrisgacsal chrisgacsal requested a review from a team as a code owner April 29, 2025 14:54
@chrisgacsal chrisgacsal added the release-note/ignore Ignore this change when generating release notes label Apr 29, 2025
@chrisgacsal chrisgacsal self-assigned this Apr 29, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 29, 2025

📝 Walkthrough

Walkthrough

This change set refactors the notification system's data model and repository layer, focusing on unifying the usage of event types. All references to the RuleType type are replaced with EventType throughout the codebase, including schema definitions, validation, input structures, and business logic. The notification repository implementation is restructured: a new adapter package is introduced, replacing the previous repository pattern and providing transactional support through a standardized interface. The service layer is updated to use this adapter and a new transaction framework for all data operations, ensuring atomicity and consistency. Event delivery status logic is moved to a dedicated file, and related methods are implemented in both the adapter and service layers. Test utilities and HTTP mapping code are updated to align with the new event type usage. Several obsolete or redundant interfaces and transaction helpers are removed.

Changes

Files / Paths Change Summary
openmeter/ent/db/mutation.go
openmeter/ent/db/notificationrule.go
openmeter/ent/db/notificationrule/notificationrule.go
openmeter/ent/db/notificationrule/where.go
openmeter/ent/db/notificationrule_create.go
openmeter/ent/schema/notification.go
All references to notification.RuleType are changed to notification.EventType for field declarations, methods, schema definitions, and enum handling. Predicate functions and validators are updated to use the new type.
openmeter/notification/rule.go Removes the RuleType alias and associated constants/methods, replacing all struct fields and logic to use EventType directly. Validation and config handling switch to EventType.
openmeter/notification/httpdriver/mapping.go
openmeter/notification/httpdriver/rule.go
Internal usage of RuleType is replaced with EventType in mapping and handler logic, including switch cases and struct field assignments.
openmeter/notification/consumer/balancetreshold.go
test/notification/repository.go
test/notification/rule.go
Updates test and consumer code to use EventTypeBalanceThreshold instead of RuleTypeBalanceThreshold for rule creation and filtering.
openmeter/notification/adapter/adapter.go Introduces a new adapter package implementing the notification.Repository interface, with transaction support, configuration validation, and context propagation.
openmeter/notification/adapter/channel.go
openmeter/notification/adapter/event.go
openmeter/notification/adapter/rule.go
Refactors all repository methods to use the new adapter type with transactional wrappers, replacing the old repository struct and direct client calls. Error handling and pagination are preserved.
openmeter/notification/adapter/deliverystatus.go Adds new methods to the adapter for listing, retrieving, and updating event delivery statuses, with transactional execution and error handling.
openmeter/notification/adapter/repository.go Removes the old repository implementation and its transaction management logic, superseded by the new adapter.
openmeter/notification/deliverystatus.go Introduces a new file defining EventDeliveryStatusState, the EventDeliveryStatus struct, input types, and validation methods for delivery status management.
openmeter/notification/event.go Removes all delivery status-related types, constants, and validation logic, moving them to the new deliverystatus file.
openmeter/notification/repository.go Refactors the repository interface to embed entutils.TxCreator, removing the explicit TxRepository interface and custom transaction helpers.
openmeter/notification/service/channel.go
openmeter/notification/service/event.go
openmeter/notification/service/rule.go
Updates the service layer to use the adapter for all data access, wrapping create, update, and delete operations in the new transaction framework. Validation and logging are preserved inside transaction functions.
openmeter/notification/service/deliverystatus.go Adds new service methods for updating, listing, and retrieving event delivery statuses, using input validation and transactional execution.
openmeter/notification/service/service.go Renames the repo field in the Service struct to adapter and updates the constructor accordingly.
openmeter/notification/webhook/svix.go Fixes error messages and refactors error aggregation logic for clarity in Svix webhook integration; no interface changes.

Possibly related PRs

  • refactor: improve notification #2742: Refactors the notification repository to an adapter pattern with updated method receivers and transaction handling, closely related to this change set's restructuring of the notification repository and adapter layers.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 66a30cc and 9d18d8e.

📒 Files selected for processing (2)
  • openmeter/notification/adapter/channel.go (1 hunks)
  • openmeter/notification/adapter/rule.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • openmeter/notification/adapter/rule.go
  • openmeter/notification/adapter/channel.go
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: E2E
  • GitHub Check: CI
  • GitHub Check: Commit hooks
  • GitHub Check: Lint
  • GitHub Check: Developer environment
  • GitHub Check: Test
  • GitHub Check: Analyze (go)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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.

Copy link
Contributor

@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: 15

🔭 Outside diff range comments (6)
openmeter/notification/rule.go (2)

174-186: 🛠️ Refactor suggestion

Validate the provided Types slice

ListRulesInput.Validate currently returns nil, so clients can pass arbitrary strings in Types which will hit the DB layer and fail later (or worse, be mishandled). Iterate over i.Types and call t.Validate() to fail fast.

 func (i ListRulesInput) Validate(_ context.Context, _ Service) error {
-    return nil
+    for _, t := range i.Types {
+        if err := t.Validate(); err != nil {
+            return err
+        }
+    }
+    return nil
 }

209-229: 🛠️ Refactor suggestion

Ensure Type and Config.Type stay in sync

CreateRuleInput.Validate checks i.Type and separately validates i.Config, but never asserts that the two refer to the same event type. A client could send {type:A, config:{type:B}} and pass validation, leading to inconsistent data.

 if err := i.Type.Validate(); err != nil {
     return err
 }
 
+if i.Config.Type != i.Type {
+    return ValidationError{
+        Err: fmt.Errorf("config.type (%s) must match input.type (%s)", i.Config.Type, i.Type),
+    }
+}
+
 if i.Name == "" {
openmeter/notification/service/rule.go (1)

42-57: ⚠️ Potential issue

External side-effects inside the DB transaction risk breaking atomicity

webhook.UpdateWebhookChannels performs network I/O. Invoking it inside the DB transaction:

  1. Prolongs the lock window.
  2. May leave the external system mutated even if the subsequent commit fails.

Consider:
• First committing the rule,
• Then updating webhooks (or using an outbox pattern).

This comment applies to DeleteRule and UpdateRule as well.

openmeter/notification/service/channel.go (3)

199-223: ⚠️ Potential issue

Use the channel’s persisted type instead of the (possibly empty) request payload

params.Type can be omitted by the caller during an update (it is optional in the API).
Relying on it after the record has already been fetched/updated may therefore resolve to the empty string and trigger the “invalid channel type” branch, even though the underlying record has a valid type.
Use the value that actually exists in the updated entity (channel.Type) when deciding which integration logic to execute.

-	switch params.Type {
+	switch channel.Type {

24-66: 🛠️ Refactor suggestion

Avoid external IO (webhook creation) inside the DB transaction

transaction.Run keeps the DB transaction open for the entire body.
Creating a webhook (s.webhook.CreateWebhook) is a network-bound operation that can ❶ hold DB locks for much longer than necessary and ❷ cannot be rolled back automatically if the DB commit later fails (e.g. because UpdateChannel errors).

A safer pattern is:

  1. Persist the channel inside the transaction (no webhook call yet) and commit.
  2. Execute the webhook creation outside the transaction.
  3. Persist the secret in a second lightweight update, or use a DB “after-commit hook” if your transaction helper supports it.

This minimises lock time and keeps the system in a consistent state even if the external call fails.


92-136: 🛠️ Refactor suggestion

Order of deletion can leave the system in an inconsistent state

Inside the transaction the webhook is deleted before the channel record (s.adapter.DeleteChannel).
If the DB delete subsequently fails or the transaction rolls back, the webhook is already gone while the channel still exists, breaking referential integrity.

Reverse the order (delete the channel first, commit, then delete the webhook) or perform the webhook deletion in an after-commit hook.

♻️ Duplicate comments (2)
openmeter/notification/rule.go (1)

259-279: 🛠️ Refactor suggestion

Mirror the Type/Config.Type consistency check in updates

Same mismatch issue applies to updates; the extra guard should be added here as well.

openmeter/notification/service/rule.go (1)

175-200: ⚠️ Potential issue

Repeat: external webhook updates executed inside the same transaction

See rationale above.

🧹 Nitpick comments (9)
openmeter/ent/schema/notification.go (2)

293-306: Keep error messages & switch tags consistent

The V arm now switches on notification.EventTypeBalanceThreshold, but the default branch still talks about an “unknown rule config type”.
That wording is correct, whereas the S arm further below still says “unknown rule type”.

To avoid future confusion, align both error messages:

-			return ruleConfig, fmt.Errorf("unknown rule type: %s", meta.Type)
+			return ruleConfig, fmt.Errorf("unknown rule config type: %s", meta.Type)

321-341: Re-evaluate coupling between RuleConfig and EventType

Using notification.EventType* to drive rule-config (de)serialization works for the single BalanceThreshold rule, but conflates two separate concepts:

  • EventType – originates from the emitted domain events (entitlements.balance.threshold, etc.).
  • RuleConfig type – describes how to interpret the data section of the rule.

If, in the future, you introduce multiple rule flavours that react to the same event type, this switch will no longer be a 1-to-1 mapping and will fail closed.

Consider a dedicated RuleConfigType enum (or embed a "kind" field) to decouple payload structure from the triggering event.

openmeter/ent/db/notificationrule/where.go (1)

294-322: Predicate overload now matches the new type – consider zero-length guard

With the parameter changed to notification.EventType, the generated predicates compile as expected.
One minor edge-case: calling TypeIn() / TypeNotIn() with zero arguments will yield an SQL fragment of IN (), which Postgres rejects.

Add a short-circuit to return predicate.False() when len(vs) == 0 to avoid runtime errors:

 func TypeIn(vs ...notification.EventType) predicate.NotificationRule {
-	v := make([]any, len(vs))
+	if len(vs) == 0 {
+		return predicate.NotificationRule(func(*sql.Selector) {}) // no-op FALSE
+	}
+	v := make([]any, len(vs))
 	for i := range v {
 		v[i] = vs[i]
 	}
 	return predicate.NotificationRule(sql.FieldIn(FieldType, v...))
 }

Same for TypeNotIn.

openmeter/notification/service/deliverystatus.go (1)

1-9: Use a pointer receiver for service methods for consistency & to prevent accidental copies

Throughout the service layer other files use the value receiver as well, which makes every call copy the Service struct (contains a logger, adapter pointer, etc.). While the struct is small, pointer receivers are the de-facto standard for service objects and avoid surprises if fields are added later.

No change required right now, but consider switching to func (s *Service) consistently.

openmeter/notification/adapter/adapter.go (1)

22-28: Clarify error wording to match generic SQL driver usage

The error message “postgres client is required” is misleading because the entdb.Client is an abstraction that could be backed by other SQL drivers in the future.
Consider re-phrasing to something like “database client is required” to avoid coupling the wording to Postgres.

-		return errors.New("postgres client is required")
+		return errors.New("database client is required")
openmeter/notification/adapter/rule.go (2)

146-147: Typo in error message

There is a small typo: “failed top delete” ➜ “failed to delete”.

-			return fmt.Errorf("failed top delete notification rule: %w", err)
+			return fmt.Errorf("failed to delete notification rule: %w", err)

196-197: Reasonable validation: ensure provided Channel IDs exist

After saving the rule you load channels but don’t validate that every requested channel was found.
Consider verifying the lengths match and returning a descriptive error to prevent silent mis-configuration.

openmeter/notification/adapter/deliverystatus.go (1)

124-126: Typo in error path

The message reads “failed to udpate …” – minor spelling fix.

-				return nil, fmt.Errorf("failed to udpate notification event delivery status: %w", err)
+				return nil, fmt.Errorf("failed to update notification event delivery status: %w", err)
openmeter/notification/service/channel.go (1)

192-195: Incorrect error message on update failure

On update failure the code returns “failed to create channel” which is misleading and complicates debugging.

-			return nil, fmt.Errorf("failed to create channel: %w", err)
+			return nil, fmt.Errorf("failed to update channel: %w", err)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a123de and d2d9091.

📒 Files selected for processing (27)
  • openmeter/ent/db/mutation.go (4 hunks)
  • openmeter/ent/db/notificationrule.go (2 hunks)
  • openmeter/ent/db/notificationrule/notificationrule.go (1 hunks)
  • openmeter/ent/db/notificationrule/where.go (2 hunks)
  • openmeter/ent/db/notificationrule_create.go (1 hunks)
  • openmeter/ent/schema/notification.go (3 hunks)
  • openmeter/notification/adapter/adapter.go (1 hunks)
  • openmeter/notification/adapter/channel.go (1 hunks)
  • openmeter/notification/adapter/deliverystatus.go (1 hunks)
  • openmeter/notification/adapter/event.go (1 hunks)
  • openmeter/notification/adapter/repository.go (0 hunks)
  • openmeter/notification/adapter/rule.go (1 hunks)
  • openmeter/notification/consumer/balancetreshold.go (1 hunks)
  • openmeter/notification/deliverystatus.go (1 hunks)
  • openmeter/notification/event.go (0 hunks)
  • openmeter/notification/httpdriver/mapping.go (3 hunks)
  • openmeter/notification/httpdriver/rule.go (1 hunks)
  • openmeter/notification/repository.go (1 hunks)
  • openmeter/notification/rule.go (6 hunks)
  • openmeter/notification/service/channel.go (6 hunks)
  • openmeter/notification/service/deliverystatus.go (1 hunks)
  • openmeter/notification/service/event.go (2 hunks)
  • openmeter/notification/service/rule.go (5 hunks)
  • openmeter/notification/service/service.go (2 hunks)
  • openmeter/notification/webhook/svix.go (2 hunks)
  • test/notification/repository.go (1 hunks)
  • test/notification/rule.go (1 hunks)
💤 Files with no reviewable changes (2)
  • openmeter/notification/event.go
  • openmeter/notification/adapter/repository.go
🧰 Additional context used
🧬 Code Graph Analysis (13)
openmeter/notification/httpdriver/rule.go (2)
openmeter/notification/event.go (2)
  • EventTypeBalanceThreshold (35-35)
  • CreateEventInput (126-138)
openmeter/notification/internal/rule.go (1)
  • NewTestEventPayload (20-94)
openmeter/notification/consumer/balancetreshold.go (1)
openmeter/notification/event.go (2)
  • EventType (38-38)
  • EventTypeBalanceThreshold (35-35)
openmeter/notification/httpdriver/mapping.go (3)
openmeter/notification/event.go (2)
  • EventType (38-38)
  • EventTypeBalanceThreshold (35-35)
openmeter/ent/db/notificationrule/notificationrule.go (1)
  • DefaultDisabled (97-97)
openmeter/notification/rule.go (2)
  • RuleConfig (93-98)
  • RuleConfigMeta (84-86)
openmeter/notification/service/service.go (1)
openmeter/notification/repository.go (1)
  • Repository (10-16)
openmeter/notification/service/rule.go (6)
openmeter/notification/service/service.go (2)
  • Service (21-30)
  • New (45-83)
openmeter/notification/rule.go (5)
  • CreateRuleInput (192-205)
  • Rule (26-42)
  • DeleteRuleInput (317-317)
  • GetRuleInput (297-297)
  • UpdateRuleInput (241-257)
pkg/models/validator.go (1)
  • Validate (16-26)
pkg/framework/transaction/transaction.go (2)
  • Run (31-49)
  • RunWithNoValue (23-28)
openmeter/notification/adapter/adapter.go (1)
  • New (33-42)
openmeter/notification/channel.go (2)
  • Channel (38-52)
  • ListChannelsInput (114-123)
openmeter/notification/service/deliverystatus.go (3)
openmeter/notification/service/service.go (1)
  • Service (21-30)
openmeter/notification/deliverystatus.go (4)
  • UpdateEventDeliveryStatusInput (122-135)
  • EventDeliveryStatus (41-54)
  • ListEventsDeliveryStatusInput (58-77)
  • GetEventDeliveryStatusInput (93-102)
pkg/framework/transaction/transaction.go (1)
  • Run (31-49)
openmeter/notification/repository.go (1)
pkg/framework/entutils/transaction.go (1)
  • TxCreator (176-176)
openmeter/notification/rule.go (1)
openmeter/notification/event.go (2)
  • EventType (38-38)
  • EventTypeBalanceThreshold (35-35)
openmeter/notification/adapter/deliverystatus.go (4)
openmeter/notification/deliverystatus.go (4)
  • ListEventsDeliveryStatusInput (58-77)
  • EventDeliveryStatus (41-54)
  • GetEventDeliveryStatusInput (93-102)
  • UpdateEventDeliveryStatusInput (122-135)
openmeter/notification/adapter/entitymapping.go (1)
  • EventDeliveryStatusFromDBEntity (115-128)
pkg/framework/entutils/transaction.go (1)
  • TransactingRepo (199-221)
openmeter/notification/adapter/adapter.go (1)
  • New (33-42)
openmeter/ent/schema/notification.go (1)
openmeter/notification/event.go (2)
  • EventType (38-38)
  • EventTypeBalanceThreshold (35-35)
test/notification/repository.go (2)
openmeter/notification/event.go (1)
  • EventTypeBalanceThreshold (35-35)
openmeter/notification/rule.go (2)
  • RuleConfig (93-98)
  • RuleConfigMeta (84-86)
openmeter/ent/db/notificationrule/where.go (3)
openmeter/ent/db/notificationrule.go (2)
  • NotificationRule (17-41)
  • NotificationRule (73-90)
openmeter/ent/schema/notification.go (5)
  • NotificationRule (66-68)
  • NotificationRule (70-76)
  • NotificationRule (78-98)
  • NotificationRule (100-106)
  • NotificationRule (108-113)
openmeter/ent/db/notificationrule/notificationrule.go (1)
  • FieldType (29-29)
openmeter/notification/adapter/channel.go (8)
openmeter/notification/channel.go (6)
  • ListChannelsInput (114-123)
  • Channel (38-52)
  • CreateChannelInput (133-144)
  • DeleteChannelInput (240-240)
  • GetChannelInput (220-220)
  • UpdateChannelInput (172-186)
openmeter/ent/db/notificationrule/where.go (1)
  • Disabled (95-97)
pkg/sortx/order.go (2)
  • OrderDefault (8-8)
  • Order (3-3)
openmeter/notification/service.go (5)
  • OrderBy (16-16)
  • OrderByCreatedAt (12-12)
  • OrderByUpdatedAt (13-13)
  • OrderByType (11-11)
  • OrderByID (10-10)
openmeter/notification/adapter/entitymapping.go (1)
  • ChannelFromDBEntity (13-37)
pkg/framework/entutils/transaction.go (2)
  • TransactingRepo (199-221)
  • TransactingRepoWithNoValue (224-236)
openmeter/notification/adapter/adapter.go (1)
  • Config (16-19)
pkg/clock/clock.go (1)
  • Now (14-21)
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Artifacts / Container image
  • GitHub Check: Test
  • GitHub Check: Quickstart
  • GitHub Check: Lint
  • GitHub Check: E2E
  • GitHub Check: Developer environment
  • GitHub Check: CI
  • GitHub Check: Analyze (go)
  • GitHub Check: Commit hooks
  • GitHub Check: Build
🔇 Additional comments (26)
openmeter/notification/httpdriver/rule.go (2)

288-288: Type unification implemented correctly.

The switch case has been updated to use notification.EventTypeBalanceThreshold instead of the previous RuleTypeBalanceThreshold, aligning with the broader refactoring effort to consolidate event types across the codebase.


294-294: Type casting removed correctly.

The explicit cast to notification.EventType has been removed as it's no longer needed, since rule.Type is now directly of type EventType. This simplifies the code while maintaining type safety.

openmeter/notification/service/service.go (2)

24-24: Repository field renamed to adapter.

The field has been renamed from repo to adapter while maintaining the notification.Repository interface type. This naming change better reflects the adapter pattern being adopted in this refactoring.


77-77: Constructor updated to match field name change.

The constructor assignment has been properly updated to use the renamed field adapter, ensuring consistency with the struct field change.

test/notification/repository.go (2)

55-55: Type constant updated in test setup.

The Type field in the CreateRuleInput has been correctly updated to use notification.EventTypeBalanceThreshold instead of RuleTypeBalanceThreshold, maintaining consistency with the type consolidation in the main codebase.


60-60: Nested type updated in rule configuration.

The Type field in the RuleConfigMeta struct has also been updated to use EventTypeBalanceThreshold, ensuring full consistency in the test fixtures with the type unification refactoring.

openmeter/ent/db/notificationrule.go (2)

30-30: Database model field type updated.

The Type field in the NotificationRule struct has been changed from notification.RuleType to notification.EventType, ensuring the database model properly represents the unified type system.


135-135: Type casting in SQL value assignment updated.

The assignment of the SQL string value now correctly casts to notification.EventType instead of the previous RuleType, maintaining consistency in the database layer with the type unification refactoring.

openmeter/ent/db/notificationrule/notificationrule.go (1)

107-107: Type parameter updated to use EventType instead of RuleType

The function parameter type has been changed from notification.RuleType to notification.EventType as part of the broader type consolidation effort mentioned in the PR objectives.

openmeter/notification/consumer/balancetreshold.go (1)

48-48: Updated type references in ListRules filter

The code now correctly uses notification.EventType and EventTypeBalanceThreshold instead of the previous RuleType, aligning with the consolidated type system across the notification domain.

test/notification/rule.go (2)

26-27: Updated type field to use EventType

This test helper now correctly uses notification.EventTypeBalanceThreshold instead of the previous RuleTypeBalanceThreshold, maintaining consistency with the production code changes.


31-32: Updated nested type references to use EventType

The RuleConfigMeta.Type field is now properly using the notification.EventTypeBalanceThreshold constant, ensuring consistency throughout the test data structure.

openmeter/ent/db/notificationrule_create.go (1)

78-81: Updated SetType method parameter type

The method now accepts notification.EventType instead of notification.RuleType, aligning with the PR's type consolidation objectives across the notification domain.

openmeter/notification/webhook/svix.go (2)

586-586: Fixed misleading error message.

The previous error message incorrectly referenced "delete Svix endpoint" instead of accurately reflecting the attempted operation. This update corrects the message to "failed to send message", which properly represents the operation being performed in the SendMessage method.


659-666: Improved error handling for Svix errors.

This is a good enhancement to the error handling logic. The previous implementation only captured the first error message from the Svix API response, potentially losing valuable debug information. The updated code properly collects all error messages from the response body and joins them together, providing more comprehensive error details to the caller.

openmeter/notification/httpdriver/mapping.go (3)

99-99: Type consolidation: RuleType replaced with EventType.

This change aligns with the PR objective of consolidating types in the notification system. Using EventType instead of RuleType creates a more consistent type system across the codebase.

Also applies to: 103-104


120-121: Consistent type usage in update request function.

Similar to the create request function, this change ensures consistent use of EventType instead of RuleType, maintaining alignment with the rest of the notification system.

Also applies to: 124-125


139-141: Standardized event type matching in switch statement.

Updated the switch statement to use EventTypeBalanceThreshold instead of RuleTypeBalanceThreshold, completing the type consolidation across the mapping layer.

openmeter/ent/db/mutation.go (5)

37424-37424: Type field updated to use EventType consistently

This change aligns with the consolidation of notification types by replacing RuleType with EventType in the struct definition. This is part of the broader refactoring to standardize on a single event type across the codebase.


37702-37703: Method signature updated to use EventType

The SetType method signature has been properly updated to use notification.EventType instead of RuleType, maintaining consistent type usage throughout the codebase.


37707-37710: Return type updated to use EventType

The GetType method signature has been correctly updated to return notification.EventType instead of RuleType, ensuring consistency with other changes in the PR.


37718-37721: OldType method updated to use EventType

The OldType method now correctly uses notification.EventType as its return type, maintaining consistency with the type consolidation effort.


38112-38115: Type assertion updated to use EventType

The type assertion in the field update handler has been properly updated to use notification.EventType, ensuring that type checking during field updates works correctly with the new type.

openmeter/ent/schema/notification.go (1)

78-84: Ensure enum migration is applied after switching from RuleType → EventType

Changing the Go type of the "type" enum from notification.RuleType to notification.EventType is source-level only.
If the underlying column was created with a Postgres ENUM (or CHECK constraint) that still references the old values, reads/writes will start failing at runtime.

Please double-check the existing DB schema. If the column is backed by an ENUM, you will need a migration similar to:

ALTER TYPE notification_rule_type RENAME TO notification_event_type;

(or recreate the constraint) before deploying the refactor.
Let me know if you want a full migration snippet generated.

openmeter/notification/repository.go (1)

6-12: 👍 Embedding TxCreator cleans up ad-hoc helpers

Replacing the bespoke WithTx* helpers with the entutils.TxCreator interface makes the transaction story consistent across packages and drops ~80 lines of boiler-plate.
Implementation structs just need to forward Tx(ctx) and WithTx(...), which are already provided by the adapter layer.

openmeter/notification/adapter/deliverystatus.go (1)

48-58: Unstable pagination without explicit ordering

ListEventsDeliveryStatus paginates without an ORDER BY. The underlying SQL engine’s default ordering is implementation-dependent, leading to item duplication or omission between pages.
Add a deterministic order (e.g., UpdatedAt DESC, ID ASC) before calling Paginate.

-		paged, err := query.Paginate(ctx, params.Page)
+		paged, err := query.
+			Order(statusdb.ByUpdatedAt(entutils.GetOrdering(sortx.OrderDesc)...), statusdb.ByID()).
+			Paginate(ctx, params.Page)

GAlexIHU
GAlexIHU previously approved these changes Apr 29, 2025
@GAlexIHU
Copy link
Contributor

I support the general direction 👍

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
openmeter/notification/adapter/event.go (1)

219-234: Consider logging when no delivery statuses are created

While the code correctly handles rules with no channels (and won't panic), consider adding a warning log when statusBulkQuery remains empty after processing all channels, to help with debugging.

 statusBulkQuery = append(statusBulkQuery, q)
 }
+
+if len(statusBulkQuery) == 0 {
+  a.logger.WarnContext(ctx, "no delivery statuses created for event",
+    "eventID", eventRow.ID,
+    "ruleID", params.RuleID,
+    "namespace", params.Namespace)
+}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d2d9091 and 66a30cc.

📒 Files selected for processing (12)
  • openmeter/notification/adapter/adapter.go (1 hunks)
  • openmeter/notification/adapter/channel.go (1 hunks)
  • openmeter/notification/adapter/deliverystatus.go (1 hunks)
  • openmeter/notification/adapter/event.go (1 hunks)
  • openmeter/notification/adapter/rule.go (1 hunks)
  • openmeter/notification/deliverystatus.go (1 hunks)
  • openmeter/notification/repository.go (1 hunks)
  • openmeter/notification/service/channel.go (6 hunks)
  • openmeter/notification/service/deliverystatus.go (1 hunks)
  • openmeter/notification/service/event.go (2 hunks)
  • openmeter/notification/service/rule.go (5 hunks)
  • openmeter/notification/service/service.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
  • openmeter/notification/service/service.go
  • openmeter/notification/adapter/deliverystatus.go
  • openmeter/notification/adapter/adapter.go
  • openmeter/notification/adapter/rule.go
  • openmeter/notification/service/deliverystatus.go
  • openmeter/notification/service/rule.go
  • openmeter/notification/service/event.go
  • openmeter/notification/deliverystatus.go
  • openmeter/notification/adapter/channel.go
  • openmeter/notification/repository.go
  • openmeter/notification/service/channel.go
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Quickstart
  • GitHub Check: E2E
  • GitHub Check: CI
  • GitHub Check: Developer environment
  • GitHub Check: Commit hooks
  • GitHub Check: Lint
  • GitHub Check: Test
  • GitHub Check: Build
  • GitHub Check: Analyze (go)
🔇 Additional comments (5)
openmeter/notification/adapter/event.go (5)

21-128: Well-structured transaction pattern in ListEvents

The implementation correctly wraps the core query logic with the transaction pattern using entutils.TransactingRepo. The filtering, pagination, and error handling look solid.


47-49: Good improvement on filtering by delivery status

Now correctly using eventdb.HasDeliveryStatusesWith to filter parent events based on child delivery status states, which ensures you only get events with at least one matching status - addressing a known issue.


130-165: GetEvent implementation follows consistent transaction pattern

The method correctly implements the transaction pattern for retrieving a single event by ID, with proper error handling for not found cases and nil results.


167-254: CreateEvent correctly implements transaction pattern

The method successfully wraps the event creation logic in a transaction, properly handles error cases, and creates delivery statuses for all channels associated with the rule.


236-241: Bulk creation of delivery statuses looks good

The implementation correctly handles the creation of delivery statuses for all channels. Note that as previously confirmed, Ent's CreateBulk won't panic with an empty slice if there are no channels.

turip
turip previously approved these changes Apr 29, 2025
tothandras
tothandras previously approved these changes Apr 29, 2025
@chrisgacsal chrisgacsal dismissed stale reviews from tothandras and turip via 9d18d8e April 29, 2025 20:47
@chrisgacsal chrisgacsal requested review from tothandras and turip April 29, 2025 20:55
@chrisgacsal chrisgacsal merged commit e3b5be4 into main Apr 29, 2025
30 checks passed
@chrisgacsal chrisgacsal deleted the refactor/notification branch April 29, 2025 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/ignore Ignore this change when generating release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants