Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Changes from all 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
7 changes: 3 additions & 4 deletions docs/orleans/grains/stateless-worker-grains.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
---
title: Stateless worker grains
description: Learn how to use stateless worker grains in .NET Orleans.
ms.date: 03/16/2022
ms.date: 01/20/2024
---

# Stateless worker grains
Expand All@@ -11,8 +11,7 @@ By default, the Orleans runtime creates no more than one activation of a grain w
When the <xref:Orleans.Concurrency.StatelessWorkerAttribute> is applied to a grain class, it indicates to the Orleans runtime that grains of that class should be treated as stateless worker grains. Stateless worker grains have the following properties that make their execution very different from that of normal grain classes.

1. The Orleans runtime can and will create multiple activations of a stateless worker grain on different silos of the cluster.
1. Requests made to stateless worker grains are always executed locally, that is on the same silo where the request originated, either made by a grain running on the silo or received by the silo's client gateway.
Hence, calls to stateless worker grains from other grains or client gateways never incur a remote message.
1. Requests made to stateless worker grains are executed locally as long as the silo is compatible, and therefore they will not incur networking or serialization costs. If the local silo is not compatible, requests are forwarded to a compatible silo.
1. The Orleans Runtime automatically creates additional activations of a stateless worker grain if the already existing ones are busy.
The maximum number of activations of a stateless worker grain the runtime creates per silo is limited by default by the number of CPU cores on the machine, unless specified explicitly by the optional `maxLocalWorkers` argument.
1. Because of 2 and 3, stateless worker grain activations are not individually addressable. Two subsequent requests to a stateless worker grain may be processed by different activations of it.
Expand All@@ -30,7 +29,7 @@ public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
```

Making a call to a stateless worker grain is the same as to any other grain.
The only difference is that in most cases a single grain ID is used, `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
The only difference is that in most cases a single grain ID is used, for example `0` or <xref:System.Guid.Empty?displayProperty=nameWithType>.
Multiple grain IDs can be used when having multiple stateless worker grain pools, one per ID is desirable.

```csharp
Expand Down