From 9df621d21b0060954c169411a656f0c07ee110f9 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Mon, 2 Jun 2025 18:23:41 +0100 Subject: [PATCH 01/19] Update Saga with note on persister specific restrictions to saga name length --- nservicebus/sagas/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index 3a50806a79a..84ad6799fe2 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -29,6 +29,9 @@ With NServiceBus, behavior is specified by writing a class that inherits from `S snippet: simple-saga +> [!NOTE] +> SQL Persistence imposes restrictions on the length of the saga name depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. + ## Long-running means stateful Any process that involves multiple network calls (or messages sent and received) has an interim state. That state may be kept in memory, persisted to disk, or stored in a distributed cache; it may be as simple as 'Response 1 received, pending response 2', but the state exists. @@ -153,6 +156,9 @@ Make sure to configure appropriate [saga persistence](/persistence/). snippet: saga-configure +> [!NOTE] +> SQL Persistence imposes restrictions on the length of the saga name depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. + ## Sagas and automatic subscriptions The auto subscription feature applies to sagas as well as the regular message handlers. From 4ac326effc916509297b5202ad72ab1cfa58d6ac Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Mon, 2 Jun 2025 18:26:33 +0100 Subject: [PATCH 02/19] Update index.md --- nservicebus/sagas/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index 84ad6799fe2..dacefa6e009 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -30,7 +30,7 @@ With NServiceBus, behavior is specified by writing a class that inherits from `S snippet: simple-saga > [!NOTE] -> SQL Persistence imposes restrictions on the length of the saga name depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. +> SQL Persistence imposes restrictions on the number of characters in the name of the saga, depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. ## Long-running means stateful @@ -157,7 +157,7 @@ Make sure to configure appropriate [saga persistence](/persistence/). snippet: saga-configure > [!NOTE] -> SQL Persistence imposes restrictions on the length of the saga name depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. +> SQL Persistence imposes restrictions on the number of characters in the name of the saga, depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. ## Sagas and automatic subscriptions From ca18e102f33e10bea431a563b89e1215d12e816a Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Fri, 20 Jun 2025 13:51:43 +0100 Subject: [PATCH 03/19] Create index_limitationnote_core_[1,).partial.md --- nservicebus/sagas/index_limitationnote_core_[1,).partial.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 nservicebus/sagas/index_limitationnote_core_[1,).partial.md diff --git a/nservicebus/sagas/index_limitationnote_core_[1,).partial.md b/nservicebus/sagas/index_limitationnote_core_[1,).partial.md new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/nservicebus/sagas/index_limitationnote_core_[1,).partial.md @@ -0,0 +1 @@ + From ab9aac7782df90d3a0be695cbca52cf1624b4fc2 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Fri, 20 Jun 2025 13:52:40 +0100 Subject: [PATCH 04/19] Update and rename index_limitationnote_core_[1,).partial.md to index_limitationnote_core_[1,].partial.md --- nservicebus/sagas/index_limitationnote_core_[1,).partial.md | 1 - nservicebus/sagas/index_limitationnote_core_[1,].partial.md | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 nservicebus/sagas/index_limitationnote_core_[1,).partial.md create mode 100644 nservicebus/sagas/index_limitationnote_core_[1,].partial.md diff --git a/nservicebus/sagas/index_limitationnote_core_[1,).partial.md b/nservicebus/sagas/index_limitationnote_core_[1,).partial.md deleted file mode 100644 index 8b137891791..00000000000 --- a/nservicebus/sagas/index_limitationnote_core_[1,).partial.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/nservicebus/sagas/index_limitationnote_core_[1,].partial.md b/nservicebus/sagas/index_limitationnote_core_[1,].partial.md new file mode 100644 index 00000000000..d94f9c2eb29 --- /dev/null +++ b/nservicebus/sagas/index_limitationnote_core_[1,].partial.md @@ -0,0 +1,2 @@ +> [!WARNING] +> Sharing property types should also be avoided. Depending on the persister implementation, sharing property types can result in storage structure being shared between endpoints. From 1cba66431ecff6b698c93af81152689631c69755 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Fri, 20 Jun 2025 13:53:19 +0100 Subject: [PATCH 05/19] Update index.md --- nservicebus/sagas/index.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index dacefa6e009..813c179b7ba 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -30,7 +30,7 @@ With NServiceBus, behavior is specified by writing a class that inherits from `S snippet: simple-saga > [!NOTE] -> SQL Persistence imposes restrictions on the number of characters in the name of the saga, depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. +> The choice of persistence can impact the design of saga data, for e.g. the length of the name of the saga class, virtual properties in saga etc. While NServiceBus persister tries to abstract things away, sometimes the limitations of the specific implementations can have an impact. ## Long-running means stateful @@ -44,8 +44,7 @@ snippet: simple-saga-data Saga data types should not be shared across different sagas. Sharing types can result in persisters physically sharing the same storage structure which should be avoided. -> [!WARNING] -> Sharing property types should also be avoided. Depending on the persister implementation, sharing property types can result in storage structure being shared between endpoints. +partial: limitationnote partial: disable-shared-state-check @@ -156,8 +155,7 @@ Make sure to configure appropriate [saga persistence](/persistence/). snippet: saga-configure -> [!NOTE] -> SQL Persistence imposes restrictions on the number of characters in the name of the saga, depending on the SQL implementation. Refer to the [implementation-specific documentation](https://docs.particular.net/persistence/sql/#supported-sql-implementations) for more details on supported name lengths. +partial: limitationnote ## Sagas and automatic subscriptions From 423e099a0133a9a2973cc5f369c704efee4adfe7 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Fri, 20 Jun 2025 13:54:31 +0100 Subject: [PATCH 06/19] Update index.md --- nservicebus/sagas/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index 813c179b7ba..82a6d5095cd 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -29,8 +29,7 @@ With NServiceBus, behavior is specified by writing a class that inherits from `S snippet: simple-saga -> [!NOTE] -> The choice of persistence can impact the design of saga data, for e.g. the length of the name of the saga class, virtual properties in saga etc. While NServiceBus persister tries to abstract things away, sometimes the limitations of the specific implementations can have an impact. +partial: limitationnote ## Long-running means stateful @@ -44,7 +43,8 @@ snippet: simple-saga-data Saga data types should not be shared across different sagas. Sharing types can result in persisters physically sharing the same storage structure which should be avoided. -partial: limitationnote +> [!WARNING] +> Sharing property types should also be avoided. Depending on the persistence implementation, sharing property types can result in the storage structure being shared between endpoints. partial: disable-shared-state-check From 7a90d70e1954a376682517b776bbe29032a8221d Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Fri, 20 Jun 2025 13:55:05 +0100 Subject: [PATCH 07/19] Update index.md --- nservicebus/sagas/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index 82a6d5095cd..0b6b11a7165 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -44,7 +44,7 @@ snippet: simple-saga-data Saga data types should not be shared across different sagas. Sharing types can result in persisters physically sharing the same storage structure which should be avoided. > [!WARNING] -> Sharing property types should also be avoided. Depending on the persistence implementation, sharing property types can result in the storage structure being shared between endpoints. +> Sharing property types should also be avoided. Depending on the persister implementation, sharing property types can result in the storage structure being shared between endpoints. partial: disable-shared-state-check From 4dd9d9f80b69b5af2dcaac5c8fd4390f729f645a Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 17:39:10 +0100 Subject: [PATCH 08/19] Update index_limitationnote_core_[1,].partial.md --- nservicebus/sagas/index_limitationnote_core_[1,].partial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nservicebus/sagas/index_limitationnote_core_[1,].partial.md b/nservicebus/sagas/index_limitationnote_core_[1,].partial.md index d94f9c2eb29..9580f1218cc 100644 --- a/nservicebus/sagas/index_limitationnote_core_[1,].partial.md +++ b/nservicebus/sagas/index_limitationnote_core_[1,].partial.md @@ -1,2 +1,2 @@ > [!WARNING] -> Sharing property types should also be avoided. Depending on the persister implementation, sharing property types can result in storage structure being shared between endpoints. +The choice of persistence can impact the design of saga data, for e.g. the length of the name of the saga class, virtual properties in saga etc. While NServiceBus persister tries to abstract things away, sometimes the limitations of the specific implementations can have an impact. From 28efb08818cf788b7221e262aec66b8ab8e0f31e Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 18:08:46 +0100 Subject: [PATCH 09/19] Update index.md --- nservicebus/sagas/index.md | 52 ++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index 0b6b11a7165..c5733ed985e 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -29,8 +29,6 @@ With NServiceBus, behavior is specified by writing a class that inherits from `S snippet: simple-saga -partial: limitationnote - ## Long-running means stateful Any process that involves multiple network calls (or messages sent and received) has an interim state. That state may be kept in memory, persisted to disk, or stored in a distributed cache; it may be as simple as 'Response 1 received, pending response 2', but the state exists. @@ -41,12 +39,15 @@ snippet: simple-saga-data ### Avoid sharing types between sagas -Saga data types should not be shared across different sagas. Sharing types can result in persisters physically sharing the same storage structure which should be avoided. +Saga data types should not be shared across different sagas. Sharing types can result in persisters physically sharing the same storage structure, which should be avoided. -> [!WARNING] -> Sharing property types should also be avoided. Depending on the persister implementation, sharing property types can result in the storage structure being shared between endpoints. +Sharing complex property types should also be avoided. Depending on the persister implementation, sharing property types can result in the storage structure being shared between endpoints. + +NServiceBus will perform a check at startup to ensure that saga data types are not shared across sagas. An exception will be thrown at startup if any shared root types are found. Complex types in properties that are shared between sagas are not included in this check. -partial: disable-shared-state-check +The startup check can be disabled by turning off the best practice validation: + +snippet: disable-shared-state-validation > [!NOTE] > If a saga property is a [record type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record), that record type must be mutable so it can be deserialized. @@ -57,31 +58,23 @@ The important part of a long-running process is its behavior. Just like regular ## Starting a saga -Since a saga manages the state of a long-running process, under which conditions should a new saga be created? Sagas are, in essence, a message driven state machine. The trigger to start this state machine is the arrival of one or more specified message types. In the previous example, a new saga is started every time a message of type `StartOrder` arrives. This is declared by adding `IAmStartedByMessages` to the saga. +Since a saga manages the state of a long-running process, under what conditions should a new saga be created? Sagas are, in essence, a message-driven state machine. The trigger to start this state machine is the arrival of one or more specified message types. In the previous example, a new saga is started every time a message of type `StartOrder` arrives. This is declared by adding `IAmStartedByMessages` to the saga. > [!NOTE] > `IHandleMessages` is redundant since `IAmStartedByMessages` already implies that. -This interface tells NServiceBus that the saga not only handles `StartOrder`, but that when that type of message arrives, a new instance of this saga should be created to handle it, if there isn't already an existing saga that correlates to the message. As a convenience, in NServiceBus version 6 and above, the message will set its mapped correlation property on the created saga data. In essence the semantics of `IAmStartedByMessages` is: - -> Create a new instance if an existing one can't be found +This interface tells NServiceBus that the saga not only handles `StartOrder`, but also that when a message of that type arrives, a new instance of this saga should be created to handle it, if there isn't already an existing saga that correlates to the message. As a convenience, in NServiceBus version 6 and above, the message will set its mapped correlation property on the created saga data. In essence, the semantics of `IAmStartedByMessages` is: +> Create a new instance of the saga if an existing instance cannot be found -> [!NOTE] -> NServiceBus requires each saga to have at least one message that is able to start it. +### Dealing with out-of-order delivery - -### Dealing with out of order delivery - -> [!NOTE] -> Always assume that messages can be delivered out of order, e.g. due to error recovery, network latency, or concurrent message processing. - -Sagas not designed to handle the arrival of messages out of order can result in some messages being discarded. In the previous example, this could happen if a `CompleteOrder` message is received before the `StartOrder` message has had a chance to create the saga. +Messages can be delivered out of order, e.g. due to error recovery, network latency, or concurrent message processing, and sagas must be designed to handle the arrival of out-of-order messages. Sagas not designed to handle the arrival of messages out of order can result in some messages being discarded. In the previous example, this could happen if a `CompleteOrder` message is received before the `StartOrder` message has had a chance to create the saga. To ensure messages are not discarded when they arrive out of order: -- Implement multiple `IAmStartedBy` interfaces for any message type that assumes the saga instance should already exist -- Override the saga not found behavior and throw an exception using `IHandleSagaNotFound` and rely on NServiceBus recoverability capability to retry messages and resolve out of order issues. +- Implement multiple `IAmStartedByMessages` interfaces for any message type that assumes the saga instance should already exist +- Override the saga not found behavior and throw an exception using `IHandleSagaNotFound` and rely on NServiceBus recoverability capability to retry messages to resolve out-of-order issues. #### Multiple message types starting a saga @@ -93,7 +86,7 @@ When messages arrive in reverse order, the handler for the `CompleteOrder` messa #### Relying on recoverability -In most scenarios, an acceptable solution to deal with out of order message delivery is to throw an exception when the saga instance does not exist. The message will be automatically retried, which may resolve the issue, or it will end up in the error queue, where it can be manually retried. +In most scenarios, an acceptable solution to deal with out-of-order message delivery is to throw an exception when the saga instance does not exist. The message will be automatically retried, which may resolve the issue; otherwise, it will be placed in the error queue, where it can be manually retried. To override the default saga not found behavior [implement `IHandleSagaNotFound` and throw an exception](saga-not-found.md). @@ -106,24 +99,23 @@ Correlation is needed in order to find existing saga instances based on data on ## Discarding messages when saga is not found -If a saga handles a message, but no related saga instance is found, then that message is discarded by default. Typically that happens when the saga has been already completed when the messages arrives and discarding the message is correct. If a different behavior is expected for specific scenarios, the default behavior [can be modified](saga-not-found.md). +If a saga handles a message but no related saga instance is found, the message is discarded by default. Typically, this happens when the saga has already been completed by the time a message arrives and discarding the message is correct. If a different behavior is expected for specific scenarios, the default behavior [can be modified](saga-not-found.md). ## Ending a saga -When a saga instance is no longer needed it can be completed using the `MarkAsComplete()` API. This tells the saga infrastructure that the instance is no longer needed and can be cleaned up. +When a saga instance is no longer needed, it can be completed using the `MarkAsComplete()` API. This tells the saga infrastructure that the instance is no longer needed and can be cleaned up. -> [!NOTE] -> Instance cleanup is implemented differently by the various saga persisters and is not guaranteed to be immediate. +Instance cleanup is implemented differently by the various saga persisters and is not guaranteed to be immediate. ### Outstanding timeouts Outstanding timeouts requested by the saga instance will be discarded when they expire without triggering the [`IHandleSagaNotFound` API](saga-not-found.md) -### Messages arriving after saga has been completed +### Messages arriving after a saga has been completed Messages that [are allowed to start a new saga instance](#starting-a-saga) will cause a new instance with the same correlation id to be created. -Messages handled by the saga(`IHandleMessages`), arriving after the saga has completed, will be passed to the [`IHandleSagaNotFound` API](saga-not-found.md). +Messages handled by the saga (`IHandleMessages`) that arrive after the saga has completed will be passed to the [`IHandleSagaNotFound` API](saga-not-found.md). ### Consistency considerations @@ -149,13 +141,13 @@ snippet: saga-with-reply This is one of the methods on the saga base class that would be very difficult to implement without tying the saga code to low-level parts of the NServiceBus infrastructure. -## Configuring saga persistence +## Saga persistence Make sure to configure appropriate [saga persistence](/persistence/). snippet: saga-configure -partial: limitationnote +The choice of persistence can impact the design of saga data, for e.g. the length of the name of the saga class, virtual properties in saga etc. While NServiceBus persister tries to abstract things away, sometimes the limitations of the specific implementations can have an impact. ## Sagas and automatic subscriptions From af110ff9bb60d57f3d69c361f7774da7018b5c0e Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 18:09:18 +0100 Subject: [PATCH 10/19] Delete nservicebus/sagas/index_limitationnote_core_[1,].partial.md --- nservicebus/sagas/index_limitationnote_core_[1,].partial.md | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 nservicebus/sagas/index_limitationnote_core_[1,].partial.md diff --git a/nservicebus/sagas/index_limitationnote_core_[1,].partial.md b/nservicebus/sagas/index_limitationnote_core_[1,].partial.md deleted file mode 100644 index 9580f1218cc..00000000000 --- a/nservicebus/sagas/index_limitationnote_core_[1,].partial.md +++ /dev/null @@ -1,2 +0,0 @@ -> [!WARNING] -The choice of persistence can impact the design of saga data, for e.g. the length of the name of the saga class, virtual properties in saga etc. While NServiceBus persister tries to abstract things away, sometimes the limitations of the specific implementations can have an impact. From 6f1a189d3326d56dc6f4573180c6e754ca4cd81b Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 18:14:35 +0100 Subject: [PATCH 11/19] Update index.md --- nservicebus/sagas/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index c5733ed985e..a9d0acb3a6d 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -2,7 +2,7 @@ title: Sagas summary: Maintain statefulness in distributed systems with the saga pattern and NServiceBus' event-driven architecture with built-in fault-tolerance and scalability. component: Core -reviewed: 2024-09-22 +reviewed: 2025-06-24 redirects: - nservicebus/sagas-in-nservicebus related: From ccc4ea6554286174d25fc5e03739513bf6fad65e Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 19:00:42 +0100 Subject: [PATCH 12/19] Added inline conditional so that the snippet is rendered only for version 8 and above. Version 7 does not show it on the docs --- nservicebus/sagas/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index a9d0acb3a6d..7d1a6c67583 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -47,8 +47,12 @@ NServiceBus will perform a check at startup to ensure that saga data types are n The startup check can be disabled by turning off the best practice validation: +#if-version [8, ) + snippet: disable-shared-state-validation +#end-if + > [!NOTE] > If a saga property is a [record type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record), that record type must be mutable so it can be deserialized. From 2dc4421a8646d68a472b6c0376ca95dfdecc2180 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 19:03:56 +0100 Subject: [PATCH 13/19] Update index.md --- nservicebus/sagas/index.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index 7d1a6c67583..a9d0acb3a6d 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -47,12 +47,8 @@ NServiceBus will perform a check at startup to ensure that saga data types are n The startup check can be disabled by turning off the best practice validation: -#if-version [8, ) - snippet: disable-shared-state-validation -#end-if - > [!NOTE] > If a saga property is a [record type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record), that record type must be mutable so it can be deserialized. From 7935c83279d24a7c1b648acb4f0c096420a89b57 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 24 Jun 2025 19:04:11 +0100 Subject: [PATCH 14/19] Update index_disable-shared-state-check_core_[8,].partial.md --- .../index_disable-shared-state-check_core_[8,].partial.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md index e4d47fa363e..1ce4cecc8d1 100644 --- a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md +++ b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md @@ -1,9 +1 @@ - -NServiceBus will perform a check at startup to ensure that saga data types are not shared across sagas. An exception will be thrown at startup if any shared root types are found. - -> [!NOTE] -> Types used in properties that are shared between sagas are not included. Depending on the persister, sharing types between saga root types can result in shared storage schema which should be avoided. - -The startup check can be disabled by turning off the best practice validation: - snippet: disable-shared-state-validation From 8e8146487a440ab7473373e6299e97c814ce5c1e Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Wed, 25 Jun 2025 11:20:31 +0200 Subject: [PATCH 15/19] Remove partial --- .../sagas/index_disable-shared-state-check_core_[8,].partial.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md diff --git a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md deleted file mode 100644 index 1ce4cecc8d1..00000000000 --- a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md +++ /dev/null @@ -1 +0,0 @@ -snippet: disable-shared-state-validation From 9cf70d9dd4a4edfcdb33dc2a7ed5c46a74a6319c Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Wed, 25 Jun 2025 11:24:16 +0200 Subject: [PATCH 16/19] Version --- Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs | 2 +- Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs b/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs index 285a423348c..1b61cee7447 100644 --- a/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs +++ b/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs @@ -15,7 +15,7 @@ public class SagaValidation { void Simple(EndpointConfiguration endpointConfiguration) { - #region disable-shared-state-validation + #region disable-shared-state-validation 8.0 endpointConfiguration.Sagas().DisableBestPracticeValidation(); diff --git a/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs b/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs index 41fbe4a92a1..de172e5e6cc 100644 --- a/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs +++ b/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs @@ -15,7 +15,7 @@ public class SagaValidation { void Simple(EndpointConfiguration endpointConfiguration) { - #region disable-shared-state-validation + #region disable-shared-state-validation 9.0 endpointConfiguration.Sagas().DisableBestPracticeValidation(); From 2a7554ef9e265317a9b7477e9dcc9240b3f9ea91 Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Wed, 25 Jun 2025 11:26:47 +0200 Subject: [PATCH 17/19] Sigh --- Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs | 2 +- Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs b/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs index 1b61cee7447..0d132eb71ee 100644 --- a/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs +++ b/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs @@ -15,7 +15,7 @@ public class SagaValidation { void Simple(EndpointConfiguration endpointConfiguration) { - #region disable-shared-state-validation 8.0 + #region disable-shared-state-validation [8.0,) endpointConfiguration.Sagas().DisableBestPracticeValidation(); diff --git a/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs b/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs index de172e5e6cc..3bb99001ac3 100644 --- a/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs +++ b/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs @@ -15,7 +15,7 @@ public class SagaValidation { void Simple(EndpointConfiguration endpointConfiguration) { - #region disable-shared-state-validation 9.0 + #region disable-shared-state-validation [9.0,) endpointConfiguration.Sagas().DisableBestPracticeValidation(); From 1e8ea0120fc71af4c15dc0b47d029916c690856b Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Wed, 25 Jun 2025 11:28:13 +0200 Subject: [PATCH 18/19] Revert "Remove partial" This reverts commit 8e8146487a440ab7473373e6299e97c814ce5c1e. --- .../sagas/index_disable-shared-state-check_core_[8,].partial.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md diff --git a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md new file mode 100644 index 00000000000..1ce4cecc8d1 --- /dev/null +++ b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md @@ -0,0 +1 @@ +snippet: disable-shared-state-validation From 4531f88a1aace2fa2cbe920cb69e0a73187dc374 Mon Sep 17 00:00:00 2001 From: Daniel Marbach Date: Wed, 25 Jun 2025 11:30:31 +0200 Subject: [PATCH 19/19] Fix --- Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs | 2 +- Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs | 2 +- nservicebus/sagas/index.md | 4 +--- .../index_disable-shared-state-check_core_[8,].partial.md | 2 ++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs b/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs index 0d132eb71ee..285a423348c 100644 --- a/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs +++ b/Snippets/Core/Core_8/Sagas/SimpleSaga/OrderSagaData.cs @@ -15,7 +15,7 @@ public class SagaValidation { void Simple(EndpointConfiguration endpointConfiguration) { - #region disable-shared-state-validation [8.0,) + #region disable-shared-state-validation endpointConfiguration.Sagas().DisableBestPracticeValidation(); diff --git a/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs b/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs index 3bb99001ac3..41fbe4a92a1 100644 --- a/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs +++ b/Snippets/Core/Core_9/Sagas/SimpleSaga/OrderSagaData.cs @@ -15,7 +15,7 @@ public class SagaValidation { void Simple(EndpointConfiguration endpointConfiguration) { - #region disable-shared-state-validation [9.0,) + #region disable-shared-state-validation endpointConfiguration.Sagas().DisableBestPracticeValidation(); diff --git a/nservicebus/sagas/index.md b/nservicebus/sagas/index.md index a9d0acb3a6d..92ba7bd0a3c 100644 --- a/nservicebus/sagas/index.md +++ b/nservicebus/sagas/index.md @@ -45,9 +45,7 @@ Sharing complex property types should also be avoided. Depending on the persiste NServiceBus will perform a check at startup to ensure that saga data types are not shared across sagas. An exception will be thrown at startup if any shared root types are found. Complex types in properties that are shared between sagas are not included in this check. -The startup check can be disabled by turning off the best practice validation: - -snippet: disable-shared-state-validation +partial: disable-shared-state-check > [!NOTE] > If a saga property is a [record type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record), that record type must be mutable so it can be deserialized. diff --git a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md index 1ce4cecc8d1..dd128432654 100644 --- a/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md +++ b/nservicebus/sagas/index_disable-shared-state-check_core_[8,].partial.md @@ -1 +1,3 @@ +The startup check can be disabled by turning off the best practice validation: + snippet: disable-shared-state-validation