I have the following transaction:
let insertPositionsAsync accountId timestamp (positions: PositionInfo list) : Async<Result<int, ExchangeError>> =
async {
try
use connection = getConnection location
do! connection.OpenAsync()
use writer =
connection.BeginBinaryImport(
$"COPY {accountId}.{tablePositionsName} (ts,instrument,average_price,leverage,unrealized_pnl,side,initial_margin,maintenance_margin,position_initial_margin,open_order_initial_margin,quantity,max_notional)
FROM STDIN (FORMAT BINARY)"
)
for t in positions do
do! writer.StartRowAsync() |> Async.AwaitTask
do! writer.WriteAsync(timestamp, NpgsqlDbType.Timestamp) |> Async.AwaitTask
do! writer.WriteAsync(t.Instrument.Ticker, NpgsqlDbType.Varchar) |> Async.AwaitTask
do! writer.WriteAsync(t.AveragePrice, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.Leverage, NpgsqlDbType.Integer) |> Async.AwaitTask
do! writer.WriteAsync(t.UnrealizedPnl, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.Side.ToString().ToLower(), NpgsqlDbType.Varchar) |> Async.AwaitTask
do! writer.WriteAsync(t.InitialMargin, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.MaintenanceMargin, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.PositionInitialMargin, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.OpenOrderInitialMargin, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.Quantity, NpgsqlDbType.Double) |> Async.AwaitTask
do! writer.WriteAsync(t.MaxNotional, NpgsqlDbType.Double) |> Async.AwaitTask
let! c = writer.CompleteAsync()
return Ok (int c)
with ex ->
error $"insertPositionsAsync {ex.Humanize()}"
return Error (ServiceException ex)
}
my understanding is that the loop:
for t in positions do
do! writer.StartRowAsync() |> Async.AwaitTask
do! writer.WriteAsync(timestamp, NpgsqlDbType.Timestamp) |> Async.AwaitTask
...
let! c = writer.CompleteAsync()
is happening in the driver and it's just collecting data in some local storage. Does it make sense to have all these async blocks then? (performance wise).
But the async API must exist for some reason. What could I be missing?
There's a discussion of this API here. It starts with someone saying:
It would be helpful to have asynchronous versions of BeginBinaryImport and BeginBinaryExport so they can be used from e.g. api endpoints without blocking the server.
For Import, given the write happens on Close/Dispose I'm guessing the write methods would not become async
However, one one of the developers then comments that:
Write can also block. So you need WriteAsync too.