Skip to content

Commit 201924e

Browse files
authored
Merge pull request #208153 from saimicrosoft/retry_logic
Add retry logic code for app stacks, Citus
2 parents 945f533 + 0fc13e6 commit 201924e

File tree

6 files changed

+318
-25
lines changed

6 files changed

+318
-25
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
author: jonels-msft
3+
ms.author: jonels
4+
ms.service: postgresql
5+
ms.subservice: hyperscale-citus
6+
ms.topic: include
7+
ms.date: 08/24/2022
8+
---
9+
10+
It's sometimes possible that database requests from your application fail.
11+
Such issues can happen under different scenarios, such as network failure
12+
between app and database, incorrect password, etc. Some issues may be
13+
transient, and resolve themselves in a few seconds to minutes. You can
14+
configure retry logic in your app to overcome the transient errors.
15+
16+
Configuring retry logic in your app helps improve the end user experience.
17+
Under failure scenarios, users will merely wait a bit longer for the
18+
application to serve requests, rather than experience errors.
19+
20+
The example below shows how to implement retry logic in your app. The sample
21+
code snippet tries a database request every 60 seconds (up to five times) until
22+
it succeeds. The number and frequency of retries can be configured based on
23+
your application's needs.

articles/postgresql/hyperscale/quickstart-app-stacks-csharp.md

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ms.service: postgresql
77
ms.subservice: hyperscale-citus
88
ms.topic: quickstart
99
recommendations: false
10-
ms.date: 08/11/2022
10+
ms.date: 08/24/2022
1111
---
1212

1313
# C# app to connect and query Hyperscale (Citus)
@@ -351,6 +351,76 @@ namespace Driver
351351
}
352352
}
353353
```
354+
## App retry during database request failures
355+
356+
[!INCLUDE[app-stack-next-steps](includes/app-stack-retry-intro.md)]
357+
358+
```csharp
359+
using System;
360+
using System.Data;
361+
using System.Runtime.InteropServices;
362+
using System.Text;
363+
using Npgsql;
364+
365+
namespace Driver
366+
{
367+
public class Reconnect
368+
{
369+
static string connStr = new NpgsqlConnectionStringBuilder("Server = <host name>; Database = citus; Port = 5432; User Id = citus; Password = {Your Password}; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50;TrustServerCertificate = true").ToString();
370+
static string executeRetry(string sql, int retryCount)
371+
{
372+
for (int i = 0; i < retryCount; i++)
373+
{
374+
try
375+
{
376+
using (var conn = new NpgsqlConnection(connStr))
377+
{
378+
conn.Open();
379+
DataTable dt = new DataTable();
380+
using (var _cmd = new NpgsqlCommand(sql, conn))
381+
{
382+
NpgsqlDataAdapter _dap = new NpgsqlDataAdapter(_cmd);
383+
_dap.Fill(dt);
384+
conn.Close();
385+
if (dt != null)
386+
{
387+
if (dt.Rows.Count > 0)
388+
{
389+
int J = dt.Rows.Count;
390+
StringBuilder sb = new StringBuilder();
391+
392+
for (int k = 0; k < dt.Rows.Count; k++)
393+
{
394+
for (int j = 0; j < dt.Columns.Count; j++)
395+
{
396+
sb.Append(dt.Rows[k][j] + ",");
397+
}
398+
sb.Remove(sb.Length - 1, 1);
399+
sb.Append("\n");
400+
}
401+
return sb.ToString();
402+
}
403+
}
404+
}
405+
}
406+
return null;
407+
}
408+
catch (Exception e)
409+
{
410+
Thread.Sleep(60000);
411+
Console.WriteLine(e.Message);
412+
}
413+
}
414+
return null;
415+
}
416+
static void Main(string[] args)
417+
{
418+
string result = executeRetry("select 1",5);
419+
Console.WriteLine(result);
420+
}
421+
}
422+
}
423+
```
354424

355425
## Next steps
356426

articles/postgresql/hyperscale/quickstart-app-stacks-java.md

Lines changed: 103 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ms.service: postgresql
77
ms.subservice: hyperscale-citus
88
ms.topic: quickstart
99
recommendations: false
10-
ms.date: 08/11/2022
10+
ms.date: 08/24/2022
1111
---
1212

1313
# Java app to connect and query Hyperscale (Citus)
@@ -109,9 +109,9 @@ Create a `src/main/resources/application.properties` file, and add:
109109

110110
``` properties
111111
driver.class.name=org.postgresql.Driver
112-
url=jdbc:postgresql://<host>:5432/citus?ssl=true&sslmode=require
113-
user=citus
114-
password=<password>
112+
db.url=jdbc:postgresql://<host>:5432/citus?ssl=true&sslmode=require
113+
db.username=citus
114+
db.password=<password>
115115
```
116116

117117
Replace the \<host\> using the Connection string that you gathered previously. Replace \<password\> with the password that you set for the database.
@@ -193,7 +193,7 @@ public class DButil {
193193
datasource.setPassword(properties.getProperty(DB_PASSWORD));
194194
datasource.setMinimumIdle(100);
195195
datasource.setMaximumPoolSize(1000000000);
196-
datasource.setAutoCommit(false);
196+
datasource.setAutoCommit(true);
197197
datasource.setLoginTimeout(3);
198198
} catch (IOException | SQLException e) {
199199
e.printStackTrace();
@@ -593,23 +593,23 @@ Executing the `main` class should now produce the following output:
593593
The following code is an example for copying in-memory data to table.
594594

595595
```java
596-
private static void inMemory(Connection connection) throws SQLException,IOException {
597-
log.info("Copying in-memory data into table");
598-
String[] input = {"0,Target,Sunnyvale,California,94001"};
599-
600-
Connection unwrap = connection.unwrap(Connection.class);
601-
BaseConnection connSec = (BaseConnection) unwrap;
602-
603-
CopyManager copyManager = new CopyManager((BaseConnection) connSec);
604-
String copyCommand = "COPY pharmacy FROM STDIN with csv";
605-
606-
for (String var : input)
596+
private static void inMemory(Connection connection) throws SQLException,IOException
607597
{
608-
Reader reader = new StringReader(var);
598+
log.info("Copying inmemory data into table");
599+
600+
final List<String> rows = new ArrayList<>();
601+
rows.add("0,Target,Sunnyvale,California,94001");
602+
rows.add("1,Apollo,Guntur,Andhra,94003");
603+
604+
final BaseConnection baseConnection = (BaseConnection) connection.unwrap(Connection.class);
605+
final CopyManager copyManager = new CopyManager(baseConnection);
606+
607+
// COPY command can change based on the format of rows. This COPY command is for above rows.
608+
final String copyCommand = "COPY pharmacy FROM STDIN with csv";
609+
610+
try (final Reader reader = new StringReader(String.join("\n", rows))) {
609611
copyManager.copyIn(copyCommand, reader);
610612
}
611-
612-
copyManager.copyIn(copyCommand);
613613
}
614614
```
615615

@@ -642,6 +642,90 @@ Executing the main class should now produce the following output:
642642
[INFO ] Closing database connection
643643
```
644644

645+
## App retry during database request failures
646+
647+
[!INCLUDE[app-stack-next-steps](includes/app-stack-retry-intro.md)]
648+
649+
```java
650+
package test.crud;
651+
652+
import java.sql.Connection;
653+
import java.sql.PreparedStatement;
654+
import java.sql.ResultSet;
655+
import java.sql.ResultSetMetaData;
656+
import java.util.logging.Logger;
657+
import com.zaxxer.hikari.HikariDataSource;
658+
659+
public class DemoApplication
660+
{
661+
private static final Logger log;
662+
663+
static
664+
{
665+
System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$-7s] %5$s %n");
666+
log = Logger.getLogger(DemoApplication.class.getName());
667+
}
668+
private static final String DB_USERNAME = "citus";
669+
private static final String DB_PASSWORD = "<Your Password>";
670+
private static final String DB_URL = "jdbc:postgresql://<Server Name>:5432/citus?sslmode=require";
671+
private static final String DB_DRIVER_CLASS = "org.postgresql.Driver";
672+
private static HikariDataSource datasource;
673+
674+
private static String executeRetry(String sql, int retryCount) throws InterruptedException
675+
{
676+
Connection con = null;
677+
PreparedStatement pst = null;
678+
ResultSet rs = null;
679+
for (int i = 1; i <= retryCount; i++)
680+
{
681+
try
682+
{
683+
datasource = new HikariDataSource();
684+
datasource.setDriverClassName(DB_DRIVER_CLASS);
685+
datasource.setJdbcUrl(DB_URL);
686+
datasource.setUsername(DB_USERNAME);
687+
datasource.setPassword(DB_PASSWORD);
688+
datasource.setMinimumIdle(10);
689+
datasource.setMaximumPoolSize(1000);
690+
datasource.setAutoCommit(true);
691+
datasource.setLoginTimeout(3);
692+
log.info("Connecting to the database");
693+
con = datasource.getConnection();
694+
log.info("Connection established");
695+
log.info("Read data");
696+
pst = con.prepareStatement(sql);
697+
rs = pst.executeQuery();
698+
StringBuilder builder = new StringBuilder();
699+
int columnCount = rs.getMetaData().getColumnCount();
700+
while (rs.next())
701+
{
702+
for (int j = 0; j < columnCount;)
703+
{
704+
builder.append(rs.getString(j + 1));
705+
if (++j < columnCount)
706+
builder.append(",");
707+
}
708+
builder.append("\r\n");
709+
}
710+
return builder.toString();
711+
}
712+
catch (Exception e)
713+
{
714+
Thread.sleep(60000);
715+
System.out.println(e.getMessage());
716+
}
717+
}
718+
return null;
719+
}
720+
721+
public static void main(String[] args) throws Exception
722+
{
723+
String result = executeRetry("select 1", 5);
724+
System.out.print(result);
725+
}
726+
}
727+
```
728+
645729
## Next steps
646730

647731
[!INCLUDE[app-stack-next-steps](includes/app-stack-next-steps.md)]

articles/postgresql/hyperscale/quickstart-app-stacks-nodejs.md

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ms.service: postgresql
77
ms.subservice: hyperscale-citus
88
ms.topic: quickstart
99
recommendations: false
10-
ms.date: 08/18/2022
10+
ms.date: 08/24/2022
1111
---
1212

1313
# Node.js app to connect and query Hyperscale (Citus)
@@ -73,10 +73,10 @@ const pool = new Pool({
7373
max: 300,
7474
connectionTimeoutMillis: 5000,
7575

76-
host: 'c.citustest.postgres.database.azure.com',
76+
host: '<host>',
7777
port: 5432,
7878
user: 'citus',
79-
password: 'Password123$',
79+
password: '<your password>',
8080
database: 'citus',
8181
ssl: true,
8282
});
@@ -387,6 +387,50 @@ async function importInMemoryDatabase() {
387387
})();
388388
```
389389

390+
## App retry during database request failures
391+
392+
[!INCLUDE[app-stack-next-steps](includes/app-stack-retry-intro.md)]
393+
394+
```javascript
395+
const { Pool } = require('pg');
396+
const { sleep } = require('sleep');
397+
398+
const pool = new Pool({
399+
host: '<host>',
400+
port: 5432,
401+
user: 'citus',
402+
password: '<your password>',
403+
database: 'citus',
404+
ssl: true,
405+
connectionTimeoutMillis: 0,
406+
idleTimeoutMillis: 0,
407+
min: 10,
408+
max: 20,
409+
});
410+
411+
(async function() {
412+
res = await executeRetry('select nonexistent_thing;',5);
413+
console.log(res);
414+
process.exit(res ? 0 : 1);
415+
})();
416+
417+
async function executeRetry(sql,retryCount)
418+
{
419+
for (let i = 0; i < retryCount; i++) {
420+
try {
421+
result = await pool.query(sql)
422+
return result;
423+
} catch (err) {
424+
console.log(err.message);
425+
sleep(60);
426+
}
427+
}
428+
429+
// didn't succeed after all the tries
430+
return null;
431+
}
432+
```
433+
390434
## Next steps
391435

392436
[!INCLUDE[app-stack-next-steps](includes/app-stack-next-steps.md)]

articles/postgresql/hyperscale/quickstart-app-stacks-python.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ms.service: postgresql
77
ms.subservice: hyperscale-citus
88
ms.topic: quickstart
99
recommendations: false
10-
ms.date: 08/11/2022
10+
ms.date: 08/24/2022
1111
---
1212

1313
# Python app to connect and query Hyperscale (Citus)
@@ -195,6 +195,43 @@ with conn.cursor() as cur:
195195
conn.commit()
196196
conn.close()
197197
```
198+
## App retry during database request failures
199+
200+
[!INCLUDE[app-stack-next-steps](includes/app-stack-retry-intro.md)]
201+
202+
```python
203+
import psycopg2
204+
import time
205+
from psycopg2 import pool
206+
207+
host = "<host>"
208+
dbname = "citus"
209+
user = "citus"
210+
password = "{your password}"
211+
sslmode = "require"
212+
213+
conn_string = "host={0} user={1} dbname={2} password={3} sslmode={4}".format(
214+
host, user, dbname, password, sslmode)
215+
postgreSQL_pool = psycopg2.pool.SimpleConnectionPool(1, 20, conn_string)
216+
217+
def executeRetry(query, retryCount):
218+
for x in range(retryCount):
219+
try:
220+
if (postgreSQL_pool):
221+
# Use getconn() to Get Connection from connection pool
222+
conn = postgreSQL_pool.getconn()
223+
cursor = conn.cursor()
224+
cursor.execute(query)
225+
return cursor.fetchall()
226+
break
227+
except Exception as err:
228+
print(err)
229+
postgreSQL_pool.putconn(conn)
230+
time.sleep(60)
231+
return None
232+
233+
print(executeRetry("select 1", 5))
234+
```
198235

199236
## Next steps
200237

0 commit comments

Comments
 (0)