---
id: 6968
title: Implement Synchronous Batching for Effect Executions
state: CLOSED
labels:
  - enhancement
assignees:
  - tobiu
createdAt: '2025-07-07T01:26:01Z'
updatedAt: '2025-07-07T11:17:38Z'
githubUrl: 'https://github.com/neomjs/neo/issues/6968'
author: tobiu
commentsCount: 0
parentIssue: null
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking: []
closedAt: '2025-07-07T11:17:38Z'
---
# Implement Synchronous Batching for Effect Executions

**Description**

This feature introduces a synchronous batching mechanism for `Neo.core.Effect` executions, ensuring that effects triggered by multiple reactive config changes within a single logical operation (e.g., `instance.set()` or direct assignments that cascade through `beforeSet`/`afterSet` hooks) are executed only once per batch. This significantly improves performance and aligns the `Effect` system with the framework's existing update cycles.

**Motivation**

Prior to this change, `Neo.core.Effect` instances would re-execute their functions immediately upon any change to their tracked `Neo.core.Config` dependencies. While correct for individual changes, this led to inefficiencies in scenarios like:

*   **`core.Base#set()` operations:** When `instance.set({propA: valA, propB: valB})` was called, each individual config change (`propA`, `propB`) would trigger a separate `Effect` run, even though the developer intended a single, batched update.
*   **Cascading `beforeSet`/`afterSet` hooks:** If a config change in a `beforeSet` or `afterSet` hook triggered another config change, the `Effect` could run multiple times within a single synchronous call stack.

This resulted in redundant computations and potential performance bottlenecks, especially for complex components with many reactive bindings.

**Changes Made**

1.  **`Neo.core.EffectBatchManager` (New Singleton: `src/core/EffectBatchManager.mjs`):**
    *   Introduced as a singleton responsible for managing the global batch state.
    *   Maintains a `batchCount` to track nested batch operations.
    *   Manages a `pendingEffects` Set to store `Effect` instances queued for execution.
    *   Provides `startBatch()`, `endBatch()`, `isBatchActive()`, and `queueEffect()` methods.

2.  **`src/core/Effect.mjs` - `run()` method modification:**
    *   The `run()` method of `Neo.core.Effect` now checks `EffectBatchManager.isBatchActive()`.
    *   If a batch is active, the `Effect` is added to `EffectBatchManager.pendingEffects` and its execution is deferred until the batch completes.
    *   If no batch is active, the `Effect` executes its function immediately.

3.  **`src/Neo.mjs` - `autoGenerateGetSet()` `set()` method modification:**
    *   This is the crucial integration point. The `set()` method within the public descriptor generated by `autoGenerateGetSet()` (which is the universal entry point for all reactive config changes) now conditionally starts and ends a batch.
    *   It checks `!Neo.core.EffectBatchManager?.isBatchActive()`. If `true`, it calls `EffectBatchManager.startBatch()` at the beginning and `EffectBatchManager.endBatch()` at the end of the `set()` operation.
    *   This ensures that *any* reactive config change, whether from `core.Base#set()` or a direct assignment, is wrapped in a batch, and any cascading changes within `beforeSet`/`afterSet` hooks participate in that same batch.

4.  **`test/siesta/tests/core/EffectBatching.mjs` (New Test File):**
    *   A comprehensive test suite has been added to validate the batching behavior.
    *   Tests cover:
        *   Multiple config changes via `instance.set()` resulting in a single `Effect` run.
        *   Individual config changes outside a batch running immediately.
        *   No-operation batches not triggering `Effect` runs.
        *   Complex scenarios involving `beforeSet` and `afterSet` hooks indirectly changing dependencies, confirming that the `Effect` still runs only once per batch.
        *   Nested batch management by `EffectBatchManager`.

**Benefits**

*   **Significant Performance Improvement:** Eliminates redundant `Effect` executions, especially in scenarios with batched updates or cascading config changes.
*   **Predictable Execution:** Ensures `Effect`s always run on the final, consistent state of their dependencies within a batch.
*   **Framework Consistency:** Aligns the `Effect` system's update cycle with the existing `core.Base#set()` batching pattern.
*   **Robustness:** Provides a more reliable and efficient foundation for all reactive data flows in Neo.mjs.

## Timeline

- 2025-07-07T01:26:01Z @tobiu assigned to @tobiu
- 2025-07-07T01:26:02Z @tobiu added the `enhancement` label
- 2025-07-07T01:27:11Z @tobiu referenced in commit `8cbebf3` - "Implement Synchronous Batching for Effect Executions #6968"
- 2025-07-07T11:17:38Z @tobiu closed this issue
- 2025-07-09T00:10:50Z @tobiu referenced in commit `37660e1` - "Implement Synchronous Batching for Effect Executions #6968"

