Skip to content

Commit b1dec85

Browse files
PhilBastianadamralphtmasternak
authored
editorial review of PostgreSQL transport docs (#6999)
Co-authored-by: Adam Ralph <[email protected]> Co-authored-by: Tomasz Masternak <[email protected]>
1 parent a1d0727 commit b1dec85

File tree

9 files changed

+66
-61
lines changed

9 files changed

+66
-61
lines changed

persistence/sql/postgresql-combining-persistence-with-transport.md

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,24 @@ related:
77
- transports/postgresql
88
---
99

10-
## Connection behavior
10+
When using [SQL persistence using the PostgreSQL dialect](/persistence/sql/dialect-postgresql.md) in combination with the [PostgreSQL transport](/transports/postgresql), the location of saga data depends both on whether the [outbox](/nservicebus/outbox/) is enabled and on the transaction mode.
1111

12-
When combining [PostgreSQL](/transports/postgresql) and [SQL persistence using the PostgreSQL dialect](/persistence/sql/dialect-postgresql.md), the connection behaves differently based on whether the [Outbox](/nservicebus/outbox/) is enabled or disabled. This influences where the saga data is stored.
12+
## Outbox disabled
1313

14-
### Without Outbox
15-
16-
PostgreSQL Transport<br/>TransactionMode | Connection sharing | Saga location
14+
PostgreSQL Transport<br/>TransactionMode | Connection sharing | Saga data location
1715
:-:|:-:|:-:
18-
SendsAtomicWithReceive | PostgreSQL Transport uses isolated transaction for send and receive | Transport DB
19-
ReceiveOnly | PostgreSQL Transport uses isolated transaction for receive | Transport DB
16+
SendsAtomicWithReceive | isolated transaction for send and receive | Transport DB
17+
ReceiveOnly | isolated transaction for receive | Transport DB
2018
None | No transactions | Persistence DB
2119

22-
#### Explicitly opting out of connection sharing when not using the Outbox
23-
24-
When an endpoint uses PostgreSQL Persistence combined with the PostgreSQL Transport with [Outbox](/nservicebus/outbox/) disabled, the persistence uses the connection and transaction context established by the transport when accessing saga data. This behavior ensures *exactly-once* message processing behavior as the state change of the saga is committed atomically while consuming the message that triggered it.
20+
With the outbox disabled, the persistence uses the connection and transaction context established by the transport to access saga data. This behavior ensures *exactly-once* message processing, since the state change of a saga is committed atomically with the consumption of the message that caused it.
2521

2622
partial: Connection
2723

28-
### With Outbox
24+
## Outbox enabled
2925

30-
PostgreSQL Transport<br/>TransactionMode | Connection sharing | Saga location
26+
PostgreSQL Transport<br/>TransactionMode | Connection sharing | Saga data location
3127
:-:|:-:|:-:
3228
SendsAtomicWithReceive | Not supported | N/A
33-
ReceiveOnly | Connection sharing via PostgreSQL Transport storage context | Persistence DB
29+
ReceiveOnly | via Transport storage context | Persistence DB
3430
None | Not supported | N/A
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
When using the [outbox](/nservicebus/outbox/), SQL Persistence always opens its own connection. In order to force using a separate connection even when the [outbox](/nservicebus/outbox/) is disabled, use the following API:
1+
This behaviour may be disabled, to force the persistance to create its own connection, as it does when the outbox is enabled:
22

33
snippet: PostgreSqlDoNotShareConnection
44

55
> [!WARNING]
6-
> In this mode NServiceBus does not guarantee *exactly-once* message processing behavior which means that saga message handling logic might be called multiple times for a single incoming message in case the previous processing attempts failed just before consuming the message.
6+
> In this mode NServiceBus does not guarantee *exactly-once* message processing behavior. A single incoming message could result in multiple calls of the saga message handling logic, if the previous processing attempt failed just before consuming the message.

samples/postgresqltransport/simple/sample.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ related:
99

1010
## Prerequisites
1111

12-
The uses a database `nservicebus`. Ensure it exists before running the sample.
12+
This sample uses a database named `nservicebus`. Ensure it exists before running the sample.
1313

1414
## Running the sample
1515

transports/postgresql/addressing.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,25 @@ component: PostgreSqlTransport
77

88
## Format
99

10-
The PostgreSQL Transport address canonical form is a schema-qualified quoted identifier:
10+
The canonical form of a PostgreSQL transport address is a schema-qualified quoted identifier:
1111

12-
```
12+
```text
1313
""table"".""schema""
1414
```
1515

16+
Only the table name is mandatory. An address containing only a table name is a valid address, e.g. `MyTable`.
17+
1618
## Resolution
1719

18-
The address is resolved into a fully-qualified table name that includes the table name and its schema. In the address, the table name is the only mandatory part. An address containing only a table name is a valid address, e.g. `MyTable`.
20+
The address is resolved into a fully-qualified table name that includes the table name and its schema.
1921

2022
### Schema
2123

22-
The PostgreSQL transport needs to know what schema to use for a queue table when sending messages. The following API can be used to specify the schema for an endpoint when [routing](/nservicebus/messaging/routing.md) is used to find a destination queue table for a message:
24+
The transport needs to determine which schema to use for a queue table when sending messages. The following API sets the schema for an endpoint when using [routing](/nservicebus/messaging/routing.md) to determine the destination queue for a message:
2325

2426
snippet: postgresql-multischema-config-for-endpoint
2527

26-
There are several cases when routing is not used and the transport needs specific configuration to find out the schema for a queue table:
28+
There are several cases when routing is not used and the transport requires specific configuration to determine the schema for a queue table:
2729

2830
- [Error queue](/nservicebus/recoverability/configure-error-handling.md#configure-the-error-queue-address)
2931
- [Audit queue](/nservicebus/operations/auditing.md#configuring-auditing)
@@ -32,11 +34,11 @@ There are several cases when routing is not used and the transport needs specifi
3234
- [Custom Checks plugin](/monitoring/custom-checks/install-plugin.md)
3335
- [Overriding the default routing mechanism](/nservicebus/messaging/send-a-message.md#overriding-the-default-routing)
3436

35-
Use the following API to configure the schema for a queue:
37+
Use the following API to set the schema for a queue:
3638

3739
snippet: postgresql-multischema-config-for-queue
3840

39-
The configuration above is applicable when sending to a queue or when a queue is passed in the configuration:
41+
The specified schema is used both when sending to a specific queue, and when a queue is set in endpoint configuration:
4042

4143
snippet: postgresql-multischema-config-for-queue-send
4244

@@ -47,10 +49,10 @@ snippet: postgresql-multischema-config-for-queue-error
4749
4850
snippet: postgresql-multischema-config-for-queue-heartbeats
4951

50-
The entire algorithm for calculating the schema is the following:
52+
The following values determine the schema, in priority order:
5153

52-
* If the schema is configured for a given queue via `UseSchemaForQueue`, the configured value is used.
53-
* If [logical routing](/nservicebus/messaging/routing.md#command-routing) is used and schema is configured for a given endpoint via `UseSchemaForEndpoint`, the configured schema is used.
54-
* If destination address contains a schema, the schema from address is used.
55-
* If default schema is configured via `DefaultSchema`, the configured value is used.
54+
* A schema configured for a given queue via `UseSchemaForQueue`.
55+
* A schema configured for a given endpoint via `UseSchemaForEndpoint`.
56+
* A schema contained in the destination address.
57+
* A default schema configured via `DefaultSchema`.
5658
* Otherwise, `public` is used as a default schema.

transports/postgresql/connection-settings.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ reviewed: 2024-05-27
55
component: PostgreSqlTransport
66
---
77

8-
## Using connection pooling
8+
## Connection pooling
99

10-
The PostgreSQL transport is built on top of [ADO.NET](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/index) and will use connection pooling. This may result in the connection pool being shared by the transport, as well as other parts of the endpoint process and the business logic.
10+
The PostgreSQL transport is built on top of [ADO.NET](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/index) and will use connection pooling. This may result in sharing of the connection pool by the transport, as well as other parts of the endpoint process and the business logic.
1111

12-
In scenarios where the concurrent message processing limit is changed, or the database connection is used for other purposes mentioned above, change the connection pool size to ensure it will not be exhausted.
12+
If increasing the concurrent message processing limit, or if the database connection is used for other purposes mentioned above, increase the connection pool size to ensure it is not exhausted.
1313

1414
> [!NOTE]
1515
> If the maximum pool size is not explicitly set on the connection string, a warning message will be logged. See also [Tuning endpoint message processing](/nservicebus/operations/tuning.md).
@@ -22,24 +22,29 @@ snippet: postgresql-config-connectionstring
2222

2323
### Token Authentication
2424

25-
To connect using token credentials, a User ID must still be supplied in the connection string with the password supplied from the access token. Given that the token is short-lived, a [data source builder must be utilized to handle password refreshes](https://devblogs.microsoft.com/dotnet/using-postgre-sql-with-dotnet-and-entra-id/). The following example uses Microsoft Entra ID.
25+
To connect using token credentials, the following must be provided in the connection string:
26+
27+
- A User ID.
28+
- The password taken from the access token.
29+
30+
Since tokens are short-lived, a [data source builder must be utilized to handle password refreshes](https://devblogs.microsoft.com/dotnet/using-postgre-sql-with-dotnet-and-entra-id/). The following example uses Microsoft Entra ID.
2631

2732
snippet: postgresql-config-entra
2833

2934
## Custom database schemas
3035

31-
The PostgreSQL transport uses `public` as a default schema. It is used for every queue if no other schema is explicitly provided in a transport address. This includes all local queues, error, audit, and remote queues of other endpoints.
36+
The transport uses `public` as a default schema. It is used for every queue if no other schema is explicitly provided in a transport address. This includes all local queues, error, audit, and remote queues of other endpoints.
3237

3338
The default schema can be overridden using the `DefaultSchema` method:
3439

3540
snippet: postgresql-non-standard-schema
3641

3742
> [!NOTE]
38-
> When subscribing to events between endpoints in different database schemas or catalogs, a [shared subscription table must be configured](/transports/postgresql/native-publish-subscribe.md#configure-subscription-table).
43+
> Subscribing to events between endpoints in different database schemas or catalogs requires a [shared subscription table to be configured](/transports/postgresql/native-publish-subscribe.md#configure-subscription-table).
3944
40-
## Custom PostgreSQL transport connection factory
45+
## Custom connection factory
4146

42-
In some environments, it might be necessary to adapt to the database server settings or to perform additional operations. This can be done by passing a custom factory method to the transport which will provide connection strings at runtime and can perform custom actions:
47+
Some environments need additional connection operations, such as adapting to the database server settings. To achieve this, pass a custom factory method to the transport that will provide connection strings at runtime and can perform custom actions:
4348

4449
snippet: postgresql-custom-connection-factory
4550

transports/postgresql/design.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ reviewed: 2024-05-28
55
component: PostgreSqlTransport
66
---
77

8-
In PostgreSQL Transport each queue is represented as table inside a database. Depending on the endpoint configuration, each endpoint might use multiple queues/tables e.g. for [callbacks](/transports/sql/callbacks.md).
8+
Each queue in PostgreSQL Transport is implemented as table inside a database. Depending on the endpoint configuration, each endpoint could use multiple queues, and therefore tables, e.g. for [callbacks](/transports/sql/callbacks.md).
99

1010
## Structure
1111

1212
The queue table consists of the following columns
1313

1414
### ID
1515

16-
The `Id` is a `uuid` generated by the sending code. It is not used by PostgreSQL transport itself.
16+
The `Id` is a `uuid` generated by the sending code. It is not used by the transport itself.
1717

1818
### Expires
1919

@@ -47,20 +47,20 @@ Messages are sent by executing an `insert` command against the queue table.
4747

4848
### Receiving
4949

50-
Messages are received by executing a `delete` command against the queue table. The `delete` is limited to a row with the lowest `Seq` not locked by other concurrent `delete`. This ensures that multiple threads within an endpoint instance and multiple instances of the same scaled-out endpoint can operate at full speed without conflicts.
50+
Messages are received by executing a `delete` command against the queue table. The `delete` is limited to a row with the lowest `Seq` not locked by any other concurrent `delete`. This ensures that multiple threads within an endpoint instance, and multiple instances of the same scaled-out endpoint, can operate at full speed without conflicts.
5151

5252
PostgreSQL transport operates in two modes: *peek* and *receive*. It starts in the *peek* mode and checks via `max(seq) - min(seq)` the number of pending messages. If the number is greater then zero, it switches to the *receive* mode and starts spawning receive tasks that use the `delete` command to receive messages.
5353

5454
The maximum number of concurrent receive tasks never exceeds the value set by `LimitMessageProcessingConcurrencyTo` (the number of tasks does not translate to the number of running threads which is controlled by the TPL scheduling mechanisms).
5555

5656
When all tasks are done the transport switches back to the *peek* mode.
5757

58-
In certain conditions, the initial estimate of a number of pending messages might be wrong e.g. when there is more than one instance of a scaled-out endpoint consuming messages from the same queue. In this case, one of the received tasks is going to fail (`delete` returns no results). When this happens, the transport immediately switches back to the *peek* mode.
58+
Under certain conditions, the initial estimate of the number of pending messages might be wrong e.g. when there is more than one instance of a scaled-out endpoint consuming messages from the same queue. In this case, one of the received tasks will fail (i.e. `delete` will return no results). When this happens, the transport immediately switches back to the *peek* mode.
5959

60-
The default peek interval, if there is has been no messages in the queue, is 1 second. The recommended range for this setting is between 100 milliseconds to 10 seconds. If a value higher than the maximum recommended settings is used, a warning message will be logged. While a value less than 100 milliseconds will put too much unnecessary stress on the database, a value larger than 10 seconds should also be used with caution as it may result in messages backing up in the queue.
60+
The [default peek interval](#behavior-queue-peek-settings-peek-delay-configuration), if no peek has yet been run or the previous peek returned no messages in the queue, is 1 second. The recommended range for this setting is between 100 milliseconds to 10 seconds. If a value higher than the maximum recommended settings is used, a warning message will be logged. While a value less than 100 milliseconds will put unnecessary stress on the database, a value larger than 10 seconds should also be used with caution as it may result in messages backing up in the queue.
6161

62-
[!NOTE]
63-
In cases where the queue peek interval is configured, care should be taken to ensure that the peek interval is not bigger than the Time-To-Be-Received(TTBR) to ensure that such messages are not discarded.
62+
> [!WARNING]
63+
> If the queue peek interval is configured, it must not be set larger than the [Time-To-Be-Received](/nservicebus/messaging/discard-old-messages.md)(TTBR) to ensure that such messages are not discarded.
6464
6565
### Queue peek settings
6666

transports/postgresql/index.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ The PostgreSQL transport implements a message queuing mechanism on top of [Postg
2424

2525
## Usage
2626

27-
A basic use of the PostgreSQL transport is as follows:
27+
A basic use of the transport is as follows:
2828

2929
snippet: usage
3030

3131
## How it works
3232

33-
PostgreSQL transport uses tables to represent queues and store messages. The PostgreSQL transport is best considered as a brokered transport, like RabbitMQ, rather than a store-and-forward transport, such as MSMQ.
33+
Tables are used to represent queues and store messages. The transport is best considered as a brokered transport, like RabbitMQ, rather than a store-and-forward transport, such as MSMQ.
3434

3535
## Advantages
3636

@@ -41,9 +41,9 @@ PostgreSQL transport uses tables to represent queues and store messages. The Pos
4141

4242
## Disadvantages
4343

44-
* No local store-and-forward mechanism; when a PostgreSQL instance is down, the endpoint cannot send nor receive messages.
44+
* No local store-and-forward mechanism; when a PostgreSQL instance is down, the endpoint cannot send or receive messages.
4545
* In centralized deployment scenarios, maximum throughput applies for the whole system, not individual endpoints. For example, if PostgreSQL can handle 2000 msg/s on the given hardware, each one of the 10 endpoints deployed on this machine can only receive a maximum of 200 msg/s (on average).
46-
* When using PostgreSQL transport, a database table serves as a queue for the messages for the endpoints. These tables are polled periodically to see if messages need to be processed by the endpoints. Although the polling interval is one second, this may still lead to delays in processing a message. For environments where low latency is required, consider using other transports that use queuing technologies, such as RabbitMQ.
46+
* When using PostgreSQL transport, a database table serves as a queue for the messages for the endpoints. These tables are polled to see if there are messages to be processed by the endpoints. Although the polling interval is, by default, one second, this may still lead to delays in processing a message. For environments where low latency is required, consider using other transports that use dedicated queuing technologies, such as RabbitMQ.
4747

4848
## Deployment considerations
4949

@@ -71,4 +71,10 @@ By default, PostgreSQL [limits the maximum number](https://www.postgresql.org/do
7171

7272
## Transactions
7373

74-
PostgreSQL transport supports following [transaction handling modes](/transports/transactions.md): receive only, send atomic with receive, and no transactions. It does not support Transaction scope mode due to the limitations in the design of the PostgreSQL database and the System.Transactions library.
74+
PostgreSQL transport supports the following [transaction handling modes](/transports/transactions.md):
75+
76+
- receive only
77+
- send atomic with receive
78+
- no transactions.
79+
80+
It does not support Transaction scope mode due to the limitations in the design of the PostgreSQL database and the System.Transactions library.

0 commit comments

Comments
 (0)