Skip to content

Type Ruby effect callback payloads - #65

Merged
cardmagic merged 3 commits into
mainfrom
feat/effect-payload-types
Sep 15, 2026
Merged

cardmagic merged 3 commits into
mainfrom
feat/effect-payload-types

Conversation

@cardmagic

Copy link
Copy Markdown
Owner

Effect callbacks expose their original arguments and outcome as serialized hashes, but typed applications had to repeat those records. This publishes reusable RBS envelope/error aliases and checks the actual constructors with strict Steep diagnostics, preserving keyword handlers and existing delivery behavior.

Closes #64. Ruby counterpart to JS #48.

Before, an application maintained its own error record:

def fail_turn: (effect_id: String, arguments: run_arguments, error: { "class" => String?, "message" => String, "backtrace" => Array[String] }) -> void

After:

def fail_turn: (effect_id: String, arguments: run_arguments, error: SolidObjects::effect_error) -> void

The full effect_failure_payload[Arguments] and effect_success_payload[Arguments, Result] aliases ship in maintained sig/public. Application parameters describe serialized values; they do not infer registered effect contracts. Ruby retains its string keys, nullable exception class, message/backtrace limits, top-level keyword invocation, retries, transactions, and idempotency keys. Generic parameters remain unconstrained because RBS cannot express Ruby serialization's normalization as a generic bound.

Validation:

  • 630 SQLite tests, 2,184 assertions, no failures/errors (15 environment-gated skips).
  • Standard, RuboCop, generated RBS validation, Steep, and Brakeman pass.
  • Built-gem consumer tests check positive examples and reject missing keys, wrong argument/error types, and mutations of the actual success/failure/error constructors.
  • Integration coverage compares complete stored/delivered payloads for public-method and block callbacks, empty arguments, every JSON result category, and retry exhaustion.
  • PostgreSQL, MySQL/mysql2, and MySQL/Trilogy run in CI.

Publish reusable RBS records and check the runtime constructors and a
packaged consumer with strict Steep diagnostics. Preserve existing
serialized hashes, keyword callbacks, and retry behavior.

Closes #64
@cardmagic

Copy link
Copy Markdown
Owner Author

@greptileai please review the current head for issue #64, including the strict constructor contracts, packaged consumer checks, and preserved Ruby callback behavior.

@greptile-apps

greptile-apps Bot commented Sep 14, 2026

Copy link
Copy Markdown

Greptile Summary

This PR publishes reusable RBS types for effect callback payloads and refactors the runtime constructors to conform to those types.

  • Adds public success, failure, and error payload aliases.
  • Strictly checks the runtime payload constructors and packaged consumer signatures.
  • Preserves callback keywords, serialized payload shapes, retries, and error truncation.
  • Adds unit, integration, and negative type-checking coverage.
  • The latest revision fixes both previous findings by testing the installed artifact and removing the redundant runtime conversion.

Confidence Score: 5/5

The PR appears safe to merge; no actionable new issue remains, and both previous findings are fully fixed.

The current implementation preserves the existing runtime payload shapes while adding strict public typing and comprehensive runtime coverage. The installed-artifact test now activates the exact built gem and verifies its resolved specification path, and the error-message constructor removes the redundant conversion while retaining a strict body-level type annotation.

Important Files Changed

Filename Overview
lib/solid_objects/effect_payload.rb Adds strictly typed constructors for success, failure, and bounded Ruby error payloads.
lib/solid_objects/effect_executor.rb Reuses the typed payload constructors without changing callback delivery or retry behavior.
sig/public/effect_payload.rbs Publishes generic success/failure envelope aliases and the reusable error record.
test/integration/effect_payload_types_test.rb Checks extracted constructors and verifies library-mode signatures against an exact installed build artifact.
test/integration/effects_test.rb Verifies complete persisted and delivered payloads across success values, callback forms, and retry exhaustion.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Effect[Effect execution] --> Outcome{Outcome}
  Outcome -->|Success| Success[EffectPayload.success]
  Outcome -->|Failure after retries| Error[EffectPayload.error]
  Error --> Failure[EffectPayload.failure]
  Success --> Message[(Durable callback message)]
  Failure --> Message
  Message --> Callback[Actor callback keywords]
  PublicRBS[Public RBS aliases] -. type-check .-> Success
  PublicRBS -. type-check .-> Error
  PublicRBS -. type-check .-> Failure
Loading

Reviews (3): Last reviewed commit: "test: isolate packaged signature loading" | Re-trigger Greptile

@cardmagic

Copy link
Copy Markdown
Owner Author

@greptileai please review the new head bfaa5d1. The Steep setup example now uses library "solid_objects", and a consumer check verifies that exact loading configuration.

Comment thread test/integration/effect_payload_types_test.rb Outdated
Comment thread lib/solid_objects/effect_payload.rb Outdated
@cardmagic

Copy link
Copy Markdown
Owner Author

@greptileai please review the new head 8987fdc. Both findings are fixed: isolated installed-artifact resolution is asserted, and the redundant conversion is replaced with a scalar type annotation. Focused strict, runtime, and formatting checks pass.

@cardmagic
cardmagic merged commit e00f4c1 into main Sep 15, 2026
60 of 61 checks passed
@cardmagic
cardmagic deleted the feat/effect-payload-types branch September 15, 2026 02:38
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.

Define typed effect callback payload contracts

1 participant