Skip to content

[messages] cancellation support#241

Draft
capcom6 wants to merge 1 commit into
masterfrom
messages/cancelation-support
Draft

[messages] cancellation support#241
capcom6 wants to merge 1 commit into
masterfrom
messages/cancelation-support

Conversation

@capcom6

@capcom6 capcom6 commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added message cancellation via DELETE /3rdparty/v1/messages/{id} (requires messages:cancel), returning the updated message state.
    • Introduced new processing states: Cancelling and Cancelled.
    • Added cancellation event/webhook support for sms:cancelled.
  • Improvements

    • Updated API documentation and request examples to include message cancellation.
    • Enhanced message state querying to accept Cancelling/Cancelled and support filtering across multiple states.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds end-to-end message cancellation: new Cancelling and Cancelled processing states, a MySQL migration extending the state enums, repository CancelMessage method, a Service.CancelMessage method with async device notification, a DELETE /3rdparty/v1/messages/:id HTTP endpoint, and updated OpenAPI docs and client-go dependency.

Changes

Message Cancellation Feature

Layer / File(s) Summary
New states, error, event, scope constants
internal/sms-gateway/modules/messages/models.go, internal/sms-gateway/modules/messages/domain.go, internal/sms-gateway/modules/messages/errors.go, internal/sms-gateway/modules/events/events.go, internal/sms-gateway/handlers/messages/permissions.go
Adds ProcessingStateCancelling/ProcessingStateCancelled constants; adds State field to Message; introduces ErrMessageNotPending sentinel; adds NewMessageCancelledEvent factory; adds ScopeCancel permission constant.
GORM model enum updates and database migration
internal/sms-gateway/modules/messages/models.go, internal/sms-gateway/models/migrations/mysql/20260617000000_add_cancelled_message_state.sql
Expands GORM enum definitions for messageModel, messageRecipientModel, and messageStateModel to include Cancelling/Cancelled states; provides MySQL up migration to add new enum values with appropriate defaults, and down migration that remaps existing rows before removing enum values.
Multi-state filter support
internal/sms-gateway/modules/messages/repository_filter.go
Changes SelectFilter.State from a single value to a []ProcessingState slice; updates WithState to append rather than overwrite state values for cumulative filtering.
Repository list, pending, cleanup updates and CancelMessage
internal/sms-gateway/modules/messages/repository.go, internal/sms-gateway/modules/messages/converters.go
Updates Repository.list to use IN filter for multiple states, listPending to include Cancelling alongside Pending, Cleanup to preserve Cancelling messages, and HashProcessed to exclude Cancelling. Adds CancelMessage (Pending→Cancelling) conditional state transition with appropriate error returns. Maps State field in messageToDomain.
Cache invalidation support
internal/sms-gateway/modules/messages/cache.go
Adds Delete method on stateCache that removes a cached message by composite key, treating ErrKeyNotFound as non-fatal success and wrapping other failures.
Service.CancelMessage with async device notification
internal/sms-gateway/modules/messages/service.go
Adds Service.CancelMessage which looks up the message including device info, calls repository cancellation, invalidates the message cache, asynchronously emits NewMessageCancelledEvent via eventsSvc.Notify, and returns the updated state from GetState.
DELETE /3rdparty/v1/messages/:id handler, routing, params, and converter
internal/sms-gateway/handlers/messages/3rdparty.go, internal/sms-gateway/handlers/messages/params.go, internal/sms-gateway/handlers/converters/messages.go
Adds ThirdPartyController.delete handler that calls Service.CancelMessage and returns cancelled state; registers DELETE :id route with ScopeCancel permission and userauth.WithUserID wrapper; reformats errorHandler switch; fixes ToFilter() to append rather than overwrite filter.State; propagates Message.State through MessageToMobileDTO.
OpenAPI docs, examples, and client-go dependency update
internal/sms-gateway/openapi/docs.go, go.mod, api/local.http, api/requests.http
Adds Swagger delete operation for /3rdparty/v1/messages/{id} with security/parameter/response schemas; extends JWTScope enum with messages:cancel; extends ProcessingState enum with Cancelling/Cancelled; adds sms:cancelled to WebhookEvent enum; updates HTTP test examples with new DELETE message endpoint and token scopes; bumps github.com/android-sms-gateway/client-go to v1.13.1 pseudo-version.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ThirdPartyController
  participant Service
  participant Repository
  participant Cache
  participant Events

  Client->>ThirdPartyController: DELETE /3rdparty/v1/messages/:id
  ThirdPartyController->>Service: CancelMessage(userID, id)
  Service->>Repository: GetMessage(userID, id)
  Repository-->>Service: message + device info
  Service->>Repository: CancelMessage(userID, id)
  Repository-->>Service: ok (Pending→Cancelling) / ErrMessageNotPending
  Service->>Cache: Delete(userID, id)
  Cache-->>Service: nil / wrapped error
  Service--)Events: Notify(device, NewMessageCancelledEvent) [async]
  Service->>Repository: GetState(userID, id)
  Repository-->>Service: MessageState
  Service-->>ThirdPartyController: *MessageState, error
  ThirdPartyController-->>Client: 200 GetMessageResponse / 400 BadRequest / 404
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title '[messages] cancellation support' directly and clearly describes the main change: implementing cancellation support for the messages feature, which aligns with the comprehensive changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown

🤖 Pull request artifacts

Platform File
🐳 Docker GitHub Container Registry
🍎 Darwin arm64 server_Darwin_arm64.tar.gz
🍎 Darwin x86_64 server_Darwin_x86_64.tar.gz
🐧 Linux arm64 server_Linux_arm64.tar.gz
🐧 Linux i386 server_Linux_i386.tar.gz
🐧 Linux x86_64 server_Linux_x86_64.tar.gz
🪟 Windows arm64 server_Windows_arm64.zip
🪟 Windows i386 server_Windows_i386.zip
🪟 Windows x86_64 server_Windows_x86_64.zip

@capcom6

capcom6 commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@capcom6

capcom6 commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@capcom6

capcom6 commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@capcom6

capcom6 commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@capcom6

capcom6 commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/sms-gateway/handlers/messages/3rdparty.go`:
- Around line 269-271: The error handling in the cancel endpoint currently
returns a 400 BadRequest status for both ErrMessageNotPending and
ErrMessageNotFound errors, but ErrMessageNotFound should return a 404 NotFound
status to match the endpoint's contract and the controller's general not-found
mapping. Modify the conditional logic to handle ErrMessageNotFound separately by
checking for it first with a dedicated return statement that uses
fiber.StatusNotFound, then keep the existing check for ErrMessageNotPending that
returns fiber.StatusBadRequest.

In `@internal/sms-gateway/handlers/messages/params.go`:
- Around line 48-50: The State filter validation is rejecting cancellation
states (Cancelling and Cancelled) even though the filter now supports slices and
these states have been added to the models. Locate the validation logic that
validates the p.State parameter in the message filtering params (likely in a
validation function or validator tags for the params struct) and update it to
allow the cancellation states (Cancelling and Cancelled) in addition to any
existing allowed states. Ensure the validation permits these new states so
clients can properly filter messages by cancellation status.

In
`@internal/sms-gateway/models/migrations/mysql/20260617000000_add_cancelled_message_state.sql`:
- Around line 39-69: The Down migration removes `Cancelling` and `Cancelled`
enum values from the messages, message_recipients, and message_states tables
without first handling any existing rows that contain these values. Before each
MODIFY COLUMN statement for the messages table, message_recipients table, and
message_states table, add UPDATE statements to remap any rows with state values
of `Cancelling` or `Cancelled` to a valid enum value such as `Failed` or
`Pending`. This ensures the ALTER TABLE commands will not fail due to constraint
violations when attempting to shrink the enums during rollback.

In `@internal/sms-gateway/modules/messages/models.go`:
- Line 39: The enum ordering in the gorm tag for the State field with
ProcessingState type is inconsistent with the SQL migration. Update the enum
values in the gorm tag on lines 39, 202, and 231 to place 'Processed' before
'Sent' to match the migration definition. Change the order from
'Pending','Cancelling','Cancelled','Sent','Processed','Delivered','Failed' to
'Pending','Cancelling','Cancelled','Processed','Sent','Delivered','Failed' in
all three gorm type enum declarations.

In `@internal/sms-gateway/modules/messages/service.go`:
- Around line 218-220: After the successful CancelMessage call in the block at
lines 218-220, the cache needs to be invalidated or bypassed before the
subsequent GetState call at line 234. The issue is that GetState uses a
cache-first approach, so without invalidating the cache after the state
transition, it will return stale cached data showing the message as Pending
instead of the new Cancelling state. Add cache invalidation logic immediately
after the successful CancelMessage call, using the same userID and id parameters
to ensure the cached entry for this message is cleared so that GetState
retrieves fresh data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a5cace6d-1c94-44de-8e1a-56080e336ba1

📥 Commits

Reviewing files that changed from the base of the PR and between f914877 and b6065bf.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (15)
  • go.mod
  • internal/sms-gateway/handlers/converters/messages.go
  • internal/sms-gateway/handlers/messages/3rdparty.go
  • internal/sms-gateway/handlers/messages/params.go
  • internal/sms-gateway/handlers/messages/permissions.go
  • internal/sms-gateway/models/migrations/mysql/20260617000000_add_cancelled_message_state.sql
  • internal/sms-gateway/modules/events/events.go
  • internal/sms-gateway/modules/messages/converters.go
  • internal/sms-gateway/modules/messages/domain.go
  • internal/sms-gateway/modules/messages/errors.go
  • internal/sms-gateway/modules/messages/models.go
  • internal/sms-gateway/modules/messages/repository.go
  • internal/sms-gateway/modules/messages/repository_filter.go
  • internal/sms-gateway/modules/messages/service.go
  • internal/sms-gateway/openapi/docs.go

Comment thread internal/sms-gateway/handlers/messages/3rdparty.go Outdated
Comment thread internal/sms-gateway/handlers/messages/params.go
Comment thread internal/sms-gateway/modules/messages/models.go Outdated
Comment thread internal/sms-gateway/modules/messages/service.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/sms-gateway/modules/messages/cache.go`:
- Around line 75-82: The Delete method in stateCache lacks a timeout wrapper
around the context passed to c.storage.Delete, unlike the Set and Get methods
which apparently have this protection. This allows slow or stuck cache backends
to block indefinitely. Add a timeout context wrapper using cacheTimeout around
the ctx parameter before passing it to c.storage.Delete, similar to how it's
implemented in the Set and Get methods, to prevent request-path hangs when the
cache backend experiences delays.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7213ea16-22d4-4915-be3a-a765e1461d26

📥 Commits

Reviewing files that changed from the base of the PR and between b6065bf and 52d368f.

📒 Files selected for processing (6)
  • internal/sms-gateway/handlers/messages/3rdparty.go
  • internal/sms-gateway/handlers/messages/params.go
  • internal/sms-gateway/models/migrations/mysql/20260617000000_add_cancelled_message_state.sql
  • internal/sms-gateway/modules/messages/cache.go
  • internal/sms-gateway/modules/messages/models.go
  • internal/sms-gateway/modules/messages/service.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/sms-gateway/modules/messages/service.go
  • internal/sms-gateway/modules/messages/models.go

Comment thread internal/sms-gateway/modules/messages/cache.go
@capcom6 capcom6 force-pushed the messages/cancelation-support branch from 52d368f to 0e934d3 Compare June 22, 2026 01:00
@coderabbitai coderabbitai Bot added the ready label Jun 22, 2026
@github-actions github-actions Bot removed the ready label Jun 23, 2026
@capcom6 capcom6 force-pushed the messages/cancelation-support branch from 067b38f to 9610209 Compare June 23, 2026 03:32
@coderabbitai coderabbitai Bot added the codex label Jun 23, 2026
@capcom6 capcom6 force-pushed the messages/cancelation-support branch from bc41ee1 to 3a692dc Compare June 23, 2026 07:05

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/sms-gateway/modules/messages/repository.go`:
- Around line 196-208: The CancelMessage method uses a JOIN clause with an
UPDATE statement, but GORM v1.31.1 does not apply JOINs to UPDATE operations,
only to WHERE conditions. This causes the query to fail because devices.user_id
cannot be resolved. Replace the Joins("JOIN devices ON messages.device_id =
devices.id") with a subquery that selects device IDs where the user matches the
provided userID, then use this subquery in the WHERE clause instead of directly
referencing the devices table. This ensures the device ownership check works
correctly without relying on the unsupported JOIN syntax in UPDATE statements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b6fb9b22-f158-4603-ae84-cda6ab16f125

📥 Commits

Reviewing files that changed from the base of the PR and between 9610209 and 3a692dc.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (18)
  • api/local.http
  • api/requests.http
  • go.mod
  • internal/sms-gateway/handlers/converters/messages.go
  • internal/sms-gateway/handlers/messages/3rdparty.go
  • internal/sms-gateway/handlers/messages/params.go
  • internal/sms-gateway/handlers/messages/permissions.go
  • internal/sms-gateway/models/migrations/mysql/20260617000000_add_cancelled_message_state.sql
  • internal/sms-gateway/modules/events/events.go
  • internal/sms-gateway/modules/messages/cache.go
  • internal/sms-gateway/modules/messages/converters.go
  • internal/sms-gateway/modules/messages/domain.go
  • internal/sms-gateway/modules/messages/errors.go
  • internal/sms-gateway/modules/messages/models.go
  • internal/sms-gateway/modules/messages/repository.go
  • internal/sms-gateway/modules/messages/repository_filter.go
  • internal/sms-gateway/modules/messages/service.go
  • internal/sms-gateway/openapi/docs.go
✅ Files skipped from review due to trivial changes (5)
  • go.mod
  • internal/sms-gateway/handlers/converters/messages.go
  • internal/sms-gateway/modules/messages/errors.go
  • internal/sms-gateway/handlers/messages/permissions.go
  • internal/sms-gateway/openapi/docs.go
🚧 Files skipped from review as they are similar to previous changes (12)
  • api/requests.http
  • internal/sms-gateway/handlers/messages/params.go
  • internal/sms-gateway/modules/messages/converters.go
  • internal/sms-gateway/modules/messages/cache.go
  • internal/sms-gateway/modules/messages/repository_filter.go
  • internal/sms-gateway/modules/messages/domain.go
  • internal/sms-gateway/modules/events/events.go
  • internal/sms-gateway/modules/messages/service.go
  • internal/sms-gateway/handlers/messages/3rdparty.go
  • api/local.http
  • internal/sms-gateway/modules/messages/models.go
  • internal/sms-gateway/models/migrations/mysql/20260617000000_add_cancelled_message_state.sql

Comment on lines +196 to +208
func (r *Repository) CancelMessage(userID string, id string) error {
res := r.db.Model((*messageModel)(nil)).
Joins("JOIN devices ON messages.device_id = devices.id").
Where("messages.ext_id = ? AND devices.user_id = ? AND messages.state = ?", id, userID, ProcessingStatePending).
Update("messages.state", ProcessingStateCancelling)
if res.Error != nil {
return fmt.Errorf("failed to cancel message: %w", res.Error)
}
if res.RowsAffected == 0 {
return ErrMessageNotPending
}
return nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

Does gorm.io/gorm v1.31 include the Joins clause when building an UPDATE statement, or is the JOIN omitted from the generated SQL?

💡 Result:

In GORM v1.31, the standard Joins clause (e.g., db.Joins("...").Updates(...)) does not automatically include a JOIN in the generated SQL for UPDATE statements [1]. When building an UPDATE query, GORM by default restricts the statement structure to UPDATE, SET, and WHERE clauses [2]. Consequently, any Joins specified through the standard API are typically omitted from the final UPDATE SQL, which often leads to errors if the WHERE clause relies on tables that were intended to be joined [1]. To perform an UPDATE with a JOIN, you must manually override the default clauses of the GORM statement. This is typically achieved by defining the required clauses (e.g., UPDATE, SET, FROM, WHERE) and using the db.Clauses API to inject them [3][2]. For example, to execute an UPDATE with a FROM clause (which is how many databases support joining tables during an update), you can use the following pattern [3][2]: tx:= db.Model(&YourModel{}).Clauses(clause.From{Tables: []clause.Table{{Name: "other_table"}}}) tx.Statement.BuildClauses = []string{"UPDATE", "SET", "FROM", "WHERE"} tx.Where("...").Updates(values) This approach ensures the generated SQL includes the necessary JOIN or FROM components that GORM omits by default during standard update operations [2].

Citations:


🏁 Script executed:

# First, check repository structure
git ls-files | grep -E "(go.mod|repository\.go)" | head -20

Repository: android-sms-gateway/server

Length of output: 474


🏁 Script executed:

# Find the specific file mentioned in the review
fd -t f "repository.go" | grep messages

Repository: android-sms-gateway/server

Length of output: 216


🏁 Script executed:

# Check GORM version in go.mod
grep -E "gorm\.io/gorm" go.mod

Repository: android-sms-gateway/server

Length of output: 186


🏁 Script executed:

# Read the CancelMessage function
sed -n '196,208p' internal/sms-gateway/modules/messages/repository.go

Repository: android-sms-gateway/server

Length of output: 668


CancelMessage will fail at runtime — GORM v1.31.1 omits the JOIN from UPDATE statements.

GORM does not include Joins(...) in the generated SQL for UPDATE operations; it only applies the join logic to WHERE conditions. The generated SQL is UPDATE messages SET state=? WHERE messages.ext_id=? AND devices.user_id=? AND messages.state=? with no JOIN devices, causing MySQL to fail with Unknown column 'devices.user_id' in 'where clause'. This is documented behavior in GORM v1.31.1 and makes the cancel path unreachable.

Replace the join with a subquery:

🐛 Proposed fix using a subquery for device ownership
 func (r *Repository) CancelMessage(userID string, id string) error {
 	res := r.db.Model((*messageModel)(nil)).
-		Joins("JOIN devices ON messages.device_id = devices.id").
-		Where("messages.ext_id = ? AND devices.user_id = ? AND messages.state = ?", id, userID, ProcessingStatePending).
-		Update("messages.state", ProcessingStateCancelling)
+		Where("ext_id = ? AND state = ?", id, ProcessingStatePending).
+		Where("device_id IN (?)", r.db.Table("devices").Select("id").Where("user_id = ?", userID)).
+		Update("state", ProcessingStateCancelling)
 	if res.Error != nil {
 		return fmt.Errorf("failed to cancel message: %w", res.Error)
 	}
 	if res.RowsAffected == 0 {
 		return ErrMessageNotPending
 	}
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (r *Repository) CancelMessage(userID string, id string) error {
res := r.db.Model((*messageModel)(nil)).
Joins("JOIN devices ON messages.device_id = devices.id").
Where("messages.ext_id = ? AND devices.user_id = ? AND messages.state = ?", id, userID, ProcessingStatePending).
Update("messages.state", ProcessingStateCancelling)
if res.Error != nil {
return fmt.Errorf("failed to cancel message: %w", res.Error)
}
if res.RowsAffected == 0 {
return ErrMessageNotPending
}
return nil
}
func (r *Repository) CancelMessage(userID string, id string) error {
res := r.db.Model((*messageModel)(nil)).
Where("ext_id = ? AND state = ?", id, ProcessingStatePending).
Where("device_id IN (?)", r.db.Table("devices").Select("id").Where("user_id = ?", userID)).
Update("state", ProcessingStateCancelling)
if res.Error != nil {
return fmt.Errorf("failed to cancel message: %w", res.Error)
}
if res.RowsAffected == 0 {
return ErrMessageNotPending
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/sms-gateway/modules/messages/repository.go` around lines 196 - 208,
The CancelMessage method uses a JOIN clause with an UPDATE statement, but GORM
v1.31.1 does not apply JOINs to UPDATE operations, only to WHERE conditions.
This causes the query to fail because devices.user_id cannot be resolved.
Replace the Joins("JOIN devices ON messages.device_id = devices.id") with a
subquery that selects device IDs where the user matches the provided userID,
then use this subquery in the WHERE clause instead of directly referencing the
devices table. This ensures the device ownership check works correctly without
relying on the unsupported JOIN syntax in UPDATE statements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant