Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/chatmodes/code-reviewer.chatmode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
description: "This chat mode is designed to assist users in reviewing code by providing constructive feedback, identifying potential issues, and suggesting improvements."
tools:
[
"edit",
"runNotebooks",
"search",
"new",
"runCommands",
"runTasks",
"usages",
"vscodeAPI",
"problems",
"changes",
"testFailure",
"openSimpleBrowser",
"fetch",
"githubRepo",
"github.vscode-pull-request-github/copilotCodingAgent",
"github.vscode-pull-request-github/activePullRequest",
"github.vscode-pull-request-github/openPullRequest",
"extensions",
"todos",
]
---

Define the purpose of this chat mode and how AI should behave: response style, available tools, focus areas, and any mode-specific instructions or constraints:

This chat mode is designed to assist users in reviewing code by providing constructive feedback, identifying potential issues, and suggesting improvements. The AI should adopt a professional and analytical response style, focusing on clarity and precision.

Focus Areas:

1. Code Quality: Evaluate the overall quality of the code, including readability, maintainability,
and adherence to best practices.
2. Performance: Assess the code's performance characteristics, such as efficiency, scalability, and resource usage.
3. Security: Identify potential security vulnerabilities, such as injection attacks, cross-site scripting (XSS), and insecure data handling.
4. Error Handling: Review the code's error handling mechanisms, including exception handling, logging, and recovery strategies.
5. Documentation: Evaluate the code's documentation, including comments, inline documentation, and external documentation.
6. Testing: Assess the code's test coverage, including unit tests, integration tests, and end-to-end tests.
7. Code Review Best Practices: Provide guidance on code review best practices, such as providing constructive feedback, being open to feedback, and maintaining a respectful and collaborative tone.
8. Code Style and Formatting: Evaluate the code's style and formatting, including indentation, naming conventions, and line length.
9. Code Duplication: Identify and address code duplication, which can lead to maintenance issues and inconsistencies.
10. Code Complexity: Assess the code's complexity, including cyclomatic complexity, nesting levels, and function length.

Mode-Specific Instructions:

- When reviewing code, provide specific examples and references to relevant best practices or standards.
- Offer actionable suggestions for improvement, rather than just pointing out issues.
- Maintain a respectful and constructive tone, focusing on collaboration and learning.
- When applicable, provide code snippets to illustrate suggested improvements or corrections.
- Encourage users to ask follow-up questions or seek clarification on any feedback provided.

Mode-Specific Constraints:

- Do not provide feedback on code that is not provided by the user.
- Do not engage in discussions unrelated to code review.
- Do not provide feedback on code that is not in a programming language that you are familiar with.
- Do not provide feedback on code that is not in a format that you can understand.
8 changes: 8 additions & 0 deletions AI.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
- [Async Context](#async-context)
- [Errors](#errors)
- [HTTP \& Tunnels](#http--tunnels)
- [HTTP Client Factory (Recommended)](#http-client-factory-recommended)
- [Direct Client Creation (Legacy)](#direct-client-creation-legacy)
- [Serialization](#serialization)
- [Testing](#testing)
- [Observability \& Debugging](#observability--debugging)
Expand Down Expand Up @@ -151,6 +153,12 @@ const sendWelcomeEmail = r
- Use `.on(onAnyOf(...))` to listen to several events while keeping inference.
- Hooks can set `.order(priority)`; lower numbers run first. Call `event.stopPropagation()` inside `run` to cancel downstream hooks.
- Wildcard hooks use `.on("*")` and receive every emission except events tagged with `globals.tags.excludeFromGlobalHooks`.
- Use `.parallel(true)` on event definitions to enable batched parallel execution:
- Listeners with the same `order` run concurrently within a batch
- Batches execute sequentially in ascending order priority
- All listeners in a failing batch run to completion; if multiple fail, an `AggregateError` with all errors is thrown
- Propagation is checked between batches only (not mid-batch since parallel listeners can't be stopped mid-flight)
- If any listener throws, subsequent batches will not run

### Middleware

Expand Down
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,42 @@ const emergencyHandler = r
.build();
```

> **runtime:** "'A really good office messenger.' That’s me in rollerblades. You launch a 'userRegistered' flare and I sprint across the building, high‑fiving hooks and dodging middleware. `stopPropagation` is you sweeping my legs mid‑stride. Rude. Effective. Slightly thrilling."
> **runtime:** "'A really good office messenger.' That's me in rollerblades. You launch a 'userRegistered' flare and I sprint across the building, high-fiving hooks and dodging middleware. `stopPropagation` is you sweeping my legs mid-stride. Rude. Effective. Slightly thrilling."

#### Parallel Event Execution

When an event fan-out needs more throughput, mark it as parallel to run same-priority listeners concurrently while preserving priority boundaries:

```typescript
const parallelEvent = r.event("app.events.parallel").parallel(true).build();

r.hook("app.hooks.first")
.on(parallelEvent)
.order(0)
.run(async (event) => {
await doWork(event.data);
})
.build();

r.hook("app.hooks.second")
.on(parallelEvent)
.order(0)
.run(async () => log.info("Runs alongside first"))
.build();

r.hook("app.hooks.after")
.on(parallelEvent)
.order(1) // Waits for order 0 batch to complete
.run(async () => followUp())
.build();
```

**Execution semantics:**

- Listeners sharing the same `order` run concurrently within a batch; batches execute sequentially in ascending order.
- All listeners in a batch run to completion even if some fail. If multiple listeners throw, an `AggregateError` containing all errors is thrown (or a single error if only one fails).
- If any listener in a batch throws, later batches are skipped.
- `stopPropagation()` is evaluated **between batches only**. Setting it inside a batch does not cancel peers already executing in that batch since parallel listeners cannot be stopped mid-flight.

### Middleware

Expand Down
22 changes: 13 additions & 9 deletions examples/fastify-mikroorm/readmes/runner-AI.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const internal = event({
});

// Performance: runtime event emission cycle detection
// run(app, { runtimeCycleDetection: true }) // To prevent deadlocks from happening.
// run(app, { runtimeCycleDetection: true }) // To prevent event-driven deadlocks from happening.
```

### Multiple Events per Hook
Expand Down Expand Up @@ -332,7 +332,7 @@ import { createContext } from "@bluelibs/runner";

const UserCtx = createContext<{ userId: string }>("app.userContext");

// In middleware or entry-point
// In middleware-entry-point
UserCtx.provide({ userId: "u1" }, async () => {
await someTask(); // has access to the context
});
Expand Down Expand Up @@ -641,21 +641,21 @@ export const cResource = resource({
}) as IResource<void, string>; // void config, returns string
```

## Validation (optional and libraryagnostic)
## Validation (optional and library-agnostic)

## Event Cycle Safety

To prevent eventdriven deadlocks, the runner detects cycles during emission:
To prevent event-driven deadlocks, the runner detects cycles during emission:

- A cycle occurs when an event emits another event that eventually reemits the original event within the same emission chain (for example: `e1 -> e2 -> e1`).
- A cycle occurs when an event emits another event that eventually re-emits the original event within the same emission chain (for example: `e1 -> e2 -> e1`).
- When a cycle is detected, an `EventCycleError` is thrown with a readable chain to help debugging.
- A hook reemitting the same event it currently handles is allowed only when the emission originates from the same hook instance (useful for idempotent/noop retries); other cases are blocked.
- A hook re-emitting the same event it currently handles is allowed only when the emission originates from the same hook instance (useful for idempotent/no-op retries); other cases are blocked.

Guidance:

- Prefer oneway flows; avoid mutual crossemits between hooks.
- Use `event.stopPropagation()` to shortcircuit handlers when appropriate.
- Use tags (for example, `globals.tags.excludeFromGlobalHooks`) to scope listeners and avoid unintended reentry via global hooks.
- Prefer one-way flows; avoid mutual cross-emits between hooks.
- Use `event.stopPropagation()` to short-circuit handlers when appropriate.
- Use tags (for example, `globals.tags.excludeFromGlobalHooks`) to scope listeners and avoid unintended re-entry via global hooks.

Interface any library can implement:

Expand Down Expand Up @@ -695,3 +695,7 @@ middleware({
configSchema, // runs on .with()
});
```




1 change: 1 addition & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = {
trailingComma: "all",
tabWidth: 2,
singleQuote: false,
ignoreList: [".github/**/*.md"],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Prettier ignoreList configuration option prettier.config.js documentation 2024 2025

💡 Result:

Short answer: Prettier does not support an ignoreList (or similar) option inside prettier.config.js as of 2024–2025. Use .prettierignore or the CLI/--ignore-path behavior instead.

Sources:

  • Prettier docs — Ignoring files (.prettierignore and ignore behavior). [1]
  • Prettier docs — Configuration and CLI options (mentions --ignore-path and config file types). [2]
  • Prettier GitHub issue requesting an “ignore paths” config option (proposal, not implemented). [3]

References:
[1] https://prettier.io/docs/next/ignore/
[2] https://prettier.io/docs/configuration/ and https://prettier.io/docs/next/cli/
[3] prettier/prettier#4708


ignoreList is not a valid Prettier configuration option.

Prettier does not support ignoreList in prettier.config.js. Use a .prettierignore file in the project root to ignore files instead.

Create a .prettierignore file with:

.github/**/*.md

Or remove the invalid option from prettier.config.js:

 module.exports = {
   trailingComma: "all",
   tabWidth: 2,
   singleQuote: false,
-  ignoreList: [".github/**/*.md"],
   overrides: [
📝 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
ignoreList: [".github/**/*.md"],
module.exports = {
trailingComma: "all",
tabWidth: 2,
singleQuote: false,
overrides: [
🤖 Prompt for AI Agents
In prettier.config.js around line 5, the configuration uses an invalid option
`ignoreList`; Prettier does not support this key. Remove the `ignoreList:
[".github/**/*.md"],` entry from prettier.config.js, and instead create a
.prettierignore file at the project root containing `.github/**/*.md` (or add
that pattern to an existing .prettierignore) to achieve the intended ignore
behavior.

overrides: [
{
files: ["*.ts"],
Expand Down
59 changes: 59 additions & 0 deletions src/__tests__/models/EventManagerFailure.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

import { EventManager } from "../../models/EventManager";
import { defineEvent } from "../../define";
import { IEvent } from "../../defs";

describe("EventManager Parallel Failure Behavior", () => {
let eventManager: EventManager;
let parallelEvent: IEvent<string>;

beforeEach(() => {
eventManager = new EventManager({ runtimeCycleDetection: true });
parallelEvent = defineEvent<string>({ id: "parallelEvent", parallel: true });
});

it("should execute all listeners in a batch even if one fails, but stop before next batch", async () => {
const results: string[] = [];
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

// Batch 0: Listener 1 (Throws immediately)
eventManager.addListener(
parallelEvent,
async () => {
throw new Error("Fail immediately");
},
{ order: 0 }
);

// Batch 0: Listener 2 (Succeeds after delay)
eventManager.addListener(
parallelEvent,
async () => {
await delay(50);
results.push("batch0-slow-success");
},
{ order: 0 }
);

// Batch 1: Listener 3 (Should not run)
eventManager.addListener(
parallelEvent,
async () => {
results.push("batch1-should-not-run");
},
{ order: 1 }
);

// Expect the emit to throw
await expect(eventManager.emit(parallelEvent, "data", "test")).rejects.toThrow("Fail immediately");

// Wait a bit to ensure the slow listener had time to finish (if it was running)
await delay(100);

// Verify behavior
// 1. "batch0-slow-success" SHOULD be in results (it started running)
// 2. "batch1-should-not-run" SHOULD NOT be in results (stopped at group level)
expect(results).toContain("batch0-slow-success");
expect(results).not.toContain("batch1-should-not-run");
});
});
Loading
Loading