4141import java .util .List ;
4242import java .util .Map ;
4343import java .util .UUID ;
44- import java .util .concurrent . TimeUnit ;
44+ import java .util .logging . Logger ;
4545import org .apache .http .client .HttpClient ;
4646import org .apache .http .client .methods .HttpPost ;
4747import org .apache .http .conn .HttpHostConnectException ;
5151import org .junit .BeforeClass ;
5252import org .junit .Test ;
5353
54-
5554public class CreateBackupTestIT {
5655 private static final String PROJECT_ENV = "GOOGLE_CLOUD_PROJECT" ;
5756 private static final String INSTANCE_ID = "ins-" + UUID .randomUUID ().toString ().substring (0 , 10 );
5857 private static final String CLUSTER_ID = "cl-" + UUID .randomUUID ().toString ().substring (0 , 10 );
5958 private static final String TABLE_ID = "tbl-" + UUID .randomUUID ().toString ().substring (0 , 10 );
6059 private static final String ZONE_ID = "us-east1-b" ;
6160 private static final String COLUMN_FAMILY_NAME = "cf1" ;
61+ private static final Logger logger = Logger .getLogger (CreateBackupTestIT .class .getName ());
6262
6363 private static String projectId ;
6464
@@ -80,34 +80,31 @@ private static String requireEnv(String varName) {
8080 @ BeforeClass
8181 public static void setUp () throws IOException {
8282 projectId = requireEnv (PROJECT_ENV );
83-
8483 try (BigtableInstanceAdminClient instanceAdmin =
8584 BigtableInstanceAdminClient .create (projectId )) {
86- CreateInstanceRequest request = CreateInstanceRequest . of ( INSTANCE_ID )
87- .addCluster (CLUSTER_ID , ZONE_ID , 1 , StorageType .SSD );
85+ CreateInstanceRequest request =
86+ CreateInstanceRequest . of ( INSTANCE_ID ) .addCluster (CLUSTER_ID , ZONE_ID , 1 , StorageType .SSD );
8887 Instance instance = instanceAdmin .createInstance (request );
8988 } catch (IOException e ) {
90- System . out . println ("Error during BeforeClass while creating instance: \n " + e .toString ());
91- throw (e );
89+ logger . info ("Error during BeforeClass while creating instance: \n " + e .toString ());
90+ throw (e );
9291 }
9392
9493 try (BigtableTableAdminClient tableAdmin =
9594 BigtableTableAdminClient .create (projectId , INSTANCE_ID )) {
9695 // Create a table.
9796 tableAdmin .createTable (CreateTableRequest .of (TABLE_ID ).addFamily (COLUMN_FAMILY_NAME ));
9897 } catch (IOException e ) {
99- System . out . println ("Error during BeforeClass while creating table: \n " + e .toString ());
100- throw (e );
98+ logger . info ("Error during BeforeClass while creating table: \n " + e .toString ());
99+ throw (e );
101100 }
102101
103102 // Get the sample's base directory (the one containing a pom.xml file)
104103 String baseDir = System .getProperty ("basedir" );
105104
106105 // Emulate the function locally by running the Functions Framework Maven plugin
107- emulatorProcess = new ProcessBuilder ()
108- .command ("mvn" , "function:run" )
109- .directory (new File (baseDir ))
110- .start ();
106+ emulatorProcess =
107+ new ProcessBuilder ().command ("mvn" , "function:run" ).directory (new File (baseDir )).start ();
111108 }
112109
113110 @ AfterClass
@@ -119,19 +116,19 @@ public static void cleanUp() throws IOException {
119116 }
120117 tableAdmin .deleteTable (TABLE_ID );
121118 } catch (IOException e ) {
122- System .out .println ("Error during AfterClass while deleting backup and table: \n "
123- + e .toString ());
124- throw (e );
119+ logger .info ("Error during AfterClass while deleting backup and table: \n " + e .toString ());
120+ throw (e );
125121 }
126122
127123 try (BigtableInstanceAdminClient instanceAdmin =
128124 BigtableInstanceAdminClient .create (projectId )) {
129125 instanceAdmin .deleteInstance (INSTANCE_ID );
130126 } catch (IOException e ) {
131- System . out . println ("Error during AfterClass while deleting instance: \n " + e .toString ());
127+ logger . info ("Error during AfterClass while deleting instance: \n " + e .toString ());
132128 throw (e );
133129 }
134- // Terminate the running Functions Framework Maven plugin process (if it's still running)
130+ // Terminate the running Functions Framework Maven plugin process (if it's still
131+ // running)
135132 if (emulatorProcess .isAlive ()) {
136133 emulatorProcess .destroy ();
137134 }
@@ -140,46 +137,65 @@ public static void cleanUp() throws IOException {
140137 @ Test
141138 public void testCreateBackup () throws Throwable {
142139 String functionUrl = BASE_URL + "/createBackup" ;
143- String msg = String .format (
144- "{\" projectId\" :\" %s\" , \" instanceId\" :\" %s\" , \" tableId\" :\" %s\" , \" clusterId\" :\" %s\" ,"
145- + "\" expireHours\" :%d}" ,
146- projectId , INSTANCE_ID , TABLE_ID , CLUSTER_ID , 8 );
140+ String msg =
141+ String .format (
142+ "{\" projectId\" :\" %s\" , \" instanceId\" :\" %s\" , \" tableId\" :\" %s\" , "
143+ + "\" clusterId\" :\" %s\" , \" expireHours\" :%d}" ,
144+ projectId , INSTANCE_ID , TABLE_ID , CLUSTER_ID , 8 );
147145 String msgBase64 = Base64 .getEncoder ().encodeToString (msg .getBytes (StandardCharsets .UTF_8 ));
148146 Map <String , String > msgMap = new HashMap <>();
149147 msgMap .put ("data" , msgBase64 );
150148 Map <String , Map <String , String >> dataMap = new HashMap <>();
151149 dataMap .put ("data" , msgMap );
152150 String jsonStr = gson .toJson (dataMap );
153151
154- HttpPost postRequest = new HttpPost (URI .create (functionUrl ));
152+ HttpPost postRequest = new HttpPost (URI .create (functionUrl ));
155153 postRequest .setEntity (new StringEntity (jsonStr ));
156154
157155 // The Functions Framework Maven plugin process takes time to start up
158156 // Use resilience4j to retry the test HTTP request until the plugin responds
159- RetryRegistry registry = RetryRegistry .of (RetryConfig .custom ()
160- .maxAttempts (8 )
161- .retryExceptions (HttpHostConnectException .class )
162- .intervalFunction (IntervalFunction .ofExponentialBackoff (200 , 2 ))
163- .build ());
157+ RetryRegistry registry =
158+ RetryRegistry .of (
159+ RetryConfig .custom ()
160+ .maxAttempts (12 )
161+ .retryExceptions (HttpHostConnectException .class )
162+ .retryOnResult (
163+ u -> {
164+ // Retry if the Functions Framework process has no stdout content
165+ // See `retryOnResultPredicate` here:
166+ // https://resilience4j.readme.io/docs/retry
167+ try {
168+ return emulatorProcess .getErrorStream ().available () == 0 ;
169+ } catch (IOException e ) {
170+ return true ;
171+ }
172+ })
173+ .intervalFunction (IntervalFunction .ofExponentialBackoff (200 , 2 ))
174+ .build ());
164175 Retry retry = registry .retry ("my" );
165176
166177 // Perform the request-retry process
167- CheckedRunnable retriableFunc = Retry . decorateCheckedRunnable (
168- retry , () -> client .execute (postRequest ));
178+ CheckedRunnable retriableFunc =
179+ Retry . decorateCheckedRunnable ( retry , () -> client .execute (postRequest ));
169180 retriableFunc .run ();
170- // Wait 2 mins for the backup to be created.
171- TimeUnit .MINUTES .sleep (2 );
181+
172182 // Check if backup exists
173183 List <String > backups = new ArrayList <String >();
174- try (BigtableTableAdminClient tableAdmin =
175- BigtableTableAdminClient .create (projectId , INSTANCE_ID )) {
176- backups = tableAdmin .listBackups (CLUSTER_ID );
177- } catch (IOException e ) {
178- System .out .println ("Unable to list backups: \n " + e .toString ());
179- throw (e );
184+ int maxAttempts = 5 ;
185+ for (int count = 0 ; count < maxAttempts ; count ++) {
186+ try (BigtableTableAdminClient tableAdmin =
187+ BigtableTableAdminClient .create (projectId , INSTANCE_ID )) {
188+ backups = tableAdmin .listBackups (CLUSTER_ID );
189+ assertThat (backups .size ()).isEqualTo (1 );
190+ String expectedBackupPrefix = TABLE_ID + "-backup-" ;
191+ assertThat (backups .get (0 ).contains (expectedBackupPrefix ));
192+ return ;
193+ } catch (Exception e ) {
194+ logger .info ("Unable to list backups: \n " + e .toString ());
195+ logger .info ("Attempt " + count + " failed. Retrying." );
196+ Thread .sleep (3000 );
197+ }
180198 }
181- assertThat (backups .size ()).isEqualTo (1 );
182- String expectedBackupPrefix = TABLE_ID + "-backup-" ;
183- assertThat (backups .get (0 ).contains (expectedBackupPrefix ));
199+ assertThat (false );
184200 }
185201}
0 commit comments