Skip to content

Allow set from loaders#600

Merged
DZakh merged 3 commits into
mainfrom
dz/allow-set-from-loaders
Jun 18, 2025
Merged

Allow set from loaders#600
DZakh merged 3 commits into
mainfrom
dz/allow-set-from-loaders

Conversation

@DZakh

@DZakh DZakh commented Jun 17, 2025

Copy link
Copy Markdown
Member

Also, hide logs on the first loader run.

I decided not to add context.once for now, since the API is arguable.

Summary by CodeRabbit

  • New Features

    • Added a silent logger option that ignores all logging calls.
    • Enhanced entity loader context with new methods for getting, setting, and deleting entities, plus a preload mode indicator.
    • Introduced a preload mode flag to loader contexts, influencing entity management and logging behavior.
  • Refactor

    • Unified and streamlined context parameter handling by replacing grouping logic with preload and save-history flags.
    • Converted entity loader context to a dynamic, proxy-based handler for flexible entity operations.
  • Tests

    • Added tests verifying entity setting and retrieval behavior during preload mode.
    • Updated tests to support new context parameters and preload mode semantics.

@DZakh DZakh requested a review from JonoPrest June 17, 2025 13:36
@DZakh

DZakh commented Jun 18, 2025

Copy link
Copy Markdown
Member Author

I'll add context.isPreload instead of context.once. After testing the change, I found it much more ergonomic to use.

@coderabbitai

coderabbitai Bot commented Jun 18, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This update refactors context parameter handling by introducing a unified contextParams type with new flags (isPreload, shouldSaveHistory), adds a no-op logger, and extends entity loader contexts with getOrCreate, set, and deleteUnsafe methods. Tests and templates are updated to align with these changes, including new test scenarios for entity setting behavior.

Changes

File(s) Change Summary
codegenerator/cli/npm/envio/src/Logging.res Added a noopLogger constant implementing all logger methods as no-ops.
codegenerator/cli/templates/dynamic/codegen/src/Types.res.hbs
codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs
Extended loader/entity context types with getOrCreate, set, deleteUnsafe methods and isPreload boolean flag.
codegenerator/cli/templates/static/codegen/src/EventProcessing.res Refactored to use unified contextParams for loader/handler arguments; loader batch now uses isPreload: true.
codegenerator/cli/templates/static/codegen/src/UserContext.res Unified context parameter types, added isPreload/shouldSaveHistory flags, switched to proxy-based entity loader context, updated traps.
scenarios/test_codegen/src/EventHandlers.ts Added a new loader test case ("loaderSetCount") to check entity set/get behavior under preload and normal modes.
scenarios/test_codegen/test/EventHandler_test.ts Added a test verifying entity.set is ignored in unordered loader runs (preload mode).
scenarios/test_codegen/test/schema_types/BigDecimal_test.res
scenarios/test_codegen/test/schema_types/Timestamp_test.res
Updated context creation to use shouldSaveHistory and isPreload instead of shouldGroup.

Sequence Diagram(s)

sequenceDiagram
    participant EventProcessor
    participant UserContext
    participant Loader
    participant EntityStore

    EventProcessor->>UserContext: Build contextParams (isPreload, shouldSaveHistory, ...)
    UserContext->>Loader: getLoaderArgs(contextParams)
    Loader->>EntityStore: getOrCreate/set/deleteUnsafe (methods depend on isPreload)
    Note right of Loader: If isPreload, set is a no-op and logger is disabled
    Loader->>UserContext: Return results
    UserContext->>EventProcessor: Handler/Loader output
Loading

Possibly related PRs

Suggested reviewers

  • JasoonS
  • JonoPrest

Poem

A rabbit hopped through fields of code,
Where preload flags and loggers strode.
Entities set, or left ignored,
With proxies new, the context soared.
Now tests all pass, the changes neat—
This code refactor is quite a feat!
🐇✨


📜 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 ca17331 and 0e8a2b4.

📒 Files selected for processing (1)
  • codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_and_test

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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (2)
codegenerator/cli/templates/static/codegen/src/UserContext.res (1)

39-46: Effect context still logs during preload

effectTraps always returns Logging.getUserLogger, so context.effect() calls inside loaders will write logs even when context.isPreload === true.
This violates the contract documented in Types.ts.hbs (“logs are ignored during preload”).

- | "log" => params.eventItem->Logging.getUserLogger->Utils.magic
+ | "log" =>
+     (params.isPreload ? Logging.noopLogger : params.eventItem->Logging.getUserLogger)
+     ->Utils.magic

Apply the same guard as in loaderTraps to keep the preload pass truly silent.

codegenerator/cli/templates/static/codegen/src/EventProcessing.res (1)

197-223: Silent exception swallow may hide real failures

runBatchLoadersOrThrow intentionally ignores both returned values and any synchronous exceptions from the first preload run.
While this avoids interrupting the batch, it can also mask programming errors inside loaders.

Consider at least logging the caught exceptions with the root logger (maybe behind a debug flag) so that silent failures are still diagnosable.

🧹 Nitpick comments (4)
codegenerator/cli/npm/envio/src/Logging.res (1)

171-177: Consider exposing full logger interface

noopLogger omits trace and fatal, although those helpers exist for the real logger.
Adding them keeps the public shape identical and avoids accidental undefined access when a caller forwards a logger.

codegenerator/cli/templates/dynamic/codegen/src/Types.res.hbs (1)

20-23: Minor style inconsistency in entityLoaderContext

Other functions in this record omit parentheses around single arguments (set: 'entity => unit).
For consistency, drop the parentheses in getOrCreate:

-  getOrCreate: ('entity) => promise<'entity>,
+  getOrCreate: 'entity => promise<'entity>,

Purely cosmetic but keeps generated code uniform.

codegenerator/cli/templates/static/codegen/src/UserContext.res (1)

213-283: Consider documenting getOrCreate semantics in preload

When isPreload is true, set is a no-op, so getOrCreate() will return the freshly-constructed entity but not persist it.
A second call inside the same preload pass will still return None, which can confuse loader authors.

Recommend adding a short note in the TS/Res templates (and maybe in docs) clarifying that getOrCreate only mutates state on the non-preload pass.

codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs (1)

19-25: Tiny wording nit

“During preload entities aren't set, logs are ignored and exceptions are silently swallowed.”
Consider rephrasing “silently swallowed” → “captured and ignored” to emphasise they are still observed internally.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 83d724f and ca17331.

📒 Files selected for processing (9)
  • codegenerator/cli/npm/envio/src/Logging.res (1 hunks)
  • codegenerator/cli/templates/dynamic/codegen/src/Types.res.hbs (1 hunks)
  • codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs (2 hunks)
  • codegenerator/cli/templates/static/codegen/src/EventProcessing.res (3 hunks)
  • codegenerator/cli/templates/static/codegen/src/UserContext.res (7 hunks)
  • scenarios/test_codegen/src/EventHandlers.ts (2 hunks)
  • scenarios/test_codegen/test/EventHandler_test.ts (1 hunks)
  • scenarios/test_codegen/test/schema_types/BigDecimal_test.res (2 hunks)
  • scenarios/test_codegen/test/schema_types/Timestamp_test.res (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_and_test
🔇 Additional comments (5)
scenarios/test_codegen/test/schema_types/BigDecimal_test.res (1)

46-48: LGTM – new context flags correctly replace shouldGroup

The test now passes explicit shouldSaveHistory and isPreload booleans; this matches the updated context API.

scenarios/test_codegen/test/schema_types/Timestamp_test.res (1)

38-40: LGTM – context parameter update is consistent

The switch to shouldSaveHistory/isPreload mirrors the loader refactor and compiles cleanly.

Also applies to: 48-50

codegenerator/cli/templates/dynamic/codegen/src/Types.res.hbs (1)

29-33: Verify downstream consumers expect isPreload before entity fields

The new isPreload field is inserted ahead of the per-entity sub-records.
Double-check that any spread/positional destructuring in generated code (e.g. let {log, effect, user, ...}) follows this order to avoid silent bugs.

scenarios/test_codegen/test/EventHandler_test.ts (1)

254-279: Test case looks correct

The additional assertion confirms that entity.set is ignored during preload runs and guards against regressions.

scenarios/test_codegen/src/EventHandlers.ts (1)

457-482: LGTM – solid coverage for isPreload behaviour

The new "loaderSetCount" branch accurately verifies that set is ignored on the preload pass and applied on the second run.
Nice defensive assertions on context.isPreload.

Comment thread codegenerator/cli/npm/envio/src/Logging.res
Comment thread codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs
Co-authored-by: Jono Prest <65739024+JonoPrest@users.noreply.github.com>
Comment on lines +210 to +211
get: (~target as params, ~prop: unknown) => {
let prop = prop->(Utils.magic: unknown => string)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why make prop unknown btw?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Because it might be either string or symbol

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ah I see

Comment on lines +213 to +223
let set = params.isPreload
? noopSet
: (entity: Internal.entity) => {
params.inMemoryStore
->InMemoryStore.getInMemTable(~entityConfig=params.entityConfig)
->InMemoryTable.Entity.set(
Set(entity)->Types.mkEntityUpdate(
~eventIdentifier=params.eventItem->makeEventIdentifier,
~entityId=entity.id,
),
~shouldSaveHistory=params.shouldSaveHistory,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should this be inlined so that it's only constructed if set is accessed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I didn't come up with a good way to inline it when I was writing the code. Although, now I have an idea, but I'll keep it like this for now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You can just use @inline and make this a function?

But its a nitpick either way.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@inline doesn't work for function inside of another function. I also tried it first :)

@JonoPrest JonoPrest left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Amazing work @DZakh, thinking it would be cool to now be able have a new api like

Contract.Event.handlerV2 that looks just like a handler and doesn't require you to invoke with the loader api

@DZakh

DZakh commented Jun 18, 2025

Copy link
Copy Markdown
Member Author

Let's better wait till v3 😁

@DZakh

DZakh commented Jun 18, 2025

Copy link
Copy Markdown
Member Author

Who knows - knows 🫡

@DZakh DZakh merged commit 4f1c18a into main Jun 18, 2025
2 checks passed
@DZakh DZakh deleted the dz/allow-set-from-loaders branch June 18, 2025 12:05
@coderabbitai coderabbitai Bot mentioned this pull request Aug 4, 2025
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