Search in sources :

Example 31 with Database

use of com.google.spanner.admin.database.v1.Database in project java-spanner by googleapis.

the class ITBackupTest method test02_RetryNonIdempotentRpcsReturningLongRunningOperations.

@Test
public void test02_RetryNonIdempotentRpcsReturningLongRunningOperations() throws Exception {
    assumeFalse("Querying long-running operations is not supported on the emulator", isUsingEmulator());
    // RPCs that return a long-running operation such as CreateDatabase, CreateBackup and
    // RestoreDatabase are non-idempotent and can normally not be automatically retried in case of a
    // transient failure. The client library will however automatically query the backend to check
    // whether the corresponding operation was started or not, and if it was, it will pick up the
    // existing operation. If no operation is found, a new RPC call will be executed to start the
    // operation.
    List<Database> databases = new ArrayList<>();
    String initialDatabaseId;
    Timestamp initialDbCreateTime;
    // CreateDatabase
    InjectErrorInterceptorProvider createDbInterceptor = new InjectErrorInterceptorProvider("CreateDatabase");
    SpannerOptions options = testHelper.getOptions().toBuilder().setInterceptorProvider(createDbInterceptor).build();
    try (Spanner spanner = options.getService()) {
        initialDatabaseId = testHelper.getUniqueDatabaseId();
        DatabaseAdminClient client = spanner.getDatabaseAdminClient();
        OperationFuture<Database, CreateDatabaseMetadata> op = client.createDatabase(testHelper.getInstanceId().getInstance(), initialDatabaseId, Collections.emptyList());
        databases.add(op.get(DATABASE_TIMEOUT_MINUTES, TimeUnit.MINUTES));
        // Keep track of the original create time of this database, as we will drop this database
        // later and create another one with the exact same name. That means that the ListOperations
        // call will return at least two CreateDatabase operations. The retry logic should always
        // pick the last one.
        initialDbCreateTime = op.get(DATABASE_TIMEOUT_MINUTES, TimeUnit.MINUTES).getCreateTime();
        // Assert that the CreateDatabase RPC was called only once, and that the operation tracking
        // was resumed through a GetOperation call.
        assertEquals(1, createDbInterceptor.methodCount.get());
        assertTrue(createDbInterceptor.getOperationCount.get() >= 1);
    }
    // CreateBackup
    InjectErrorInterceptorProvider createBackupInterceptor = new InjectErrorInterceptorProvider("CreateBackup");
    options = testHelper.getOptions().toBuilder().setInterceptorProvider(createBackupInterceptor).build();
    String backupId = String.format("test-bck-%08d", new Random().nextInt(100000000));
    try (Spanner spanner = options.getService()) {
        String databaseId = databases.get(0).getId().getDatabase();
        DatabaseAdminClient client = spanner.getDatabaseAdminClient();
        OperationFuture<Backup, CreateBackupMetadata> op = client.createBackup(testHelper.getInstanceId().getInstance(), backupId, databaseId, Timestamp.ofTimeSecondsAndNanos(Timestamp.now().getSeconds() + TimeUnit.SECONDS.convert(7L, TimeUnit.DAYS), 0));
        Stopwatch watch = Stopwatch.createStarted();
        while (createBackupInterceptor.methodCount.get() < 1 && createBackupInterceptor.getOperationCount.get() < 1 && watch.elapsed(TimeUnit.SECONDS) < 120) {
            // noinspection BusyWait
            Thread.sleep(5000L);
        }
        client.cancelOperation(op.getName());
        // Assert that the CreateBackup RPC was called only once, and that the operation tracking
        // was resumed through a GetOperation call.
        assertEquals(1, createBackupInterceptor.methodCount.get());
        assertTrue(createBackupInterceptor.getOperationCount.get() >= 1);
    }
    // RestoreBackup
    if (!backups.isEmpty()) {
        InjectErrorInterceptorProvider restoreBackupInterceptor = new InjectErrorInterceptorProvider("RestoreDatabase");
        options = testHelper.getOptions().toBuilder().setInterceptorProvider(restoreBackupInterceptor).build();
        try (Spanner spanner = options.getService()) {
            String restoredDbId = testHelper.getUniqueDatabaseId();
            DatabaseAdminClient client = spanner.getDatabaseAdminClient();
            OperationFuture<Database, RestoreDatabaseMetadata> op = client.restoreDatabase(testHelper.getInstanceId().getInstance(), backups.get(0), testHelper.getInstanceId().getInstance(), restoredDbId);
            Stopwatch watch = Stopwatch.createStarted();
            while (restoreBackupInterceptor.methodCount.get() < 1 && restoreBackupInterceptor.getOperationCount.get() < 1 && watch.elapsed(TimeUnit.SECONDS) < 120) {
                // noinspection BusyWait
                Thread.sleep(5000L);
            }
            try {
                client.cancelOperation(op.getName());
            } catch (SpannerException | ExecutionException e) {
            // Ignore, this can happen, as the restore operation sometimes fails to start if there
            // is already a restore operation running on the instance.
            }
            // Assert that the RestoreDatabase RPC was called only once, and that the operation
            // tracking was resumed through a GetOperation call.
            assertEquals(1, restoreBackupInterceptor.methodCount.get());
            assertTrue(restoreBackupInterceptor.getOperationCount.get() >= 1);
        }
    }
    // Create another database with the exact same name as the first database.
    createDbInterceptor = new InjectErrorInterceptorProvider("CreateDatabase");
    options = testHelper.getOptions().toBuilder().setInterceptorProvider(createDbInterceptor).build();
    try (Spanner spanner = options.getService()) {
        DatabaseAdminClient client = spanner.getDatabaseAdminClient();
        // First drop the initial database.
        client.dropDatabase(testHelper.getInstanceId().getInstance(), initialDatabaseId);
        // Now re-create a database with the exact same name.
        OperationFuture<Database, CreateDatabaseMetadata> op = client.createDatabase(testHelper.getInstanceId().getInstance(), initialDatabaseId, Collections.emptyList());
        // Check that the second database was created and has a greater creation time than the
        // first.
        Timestamp secondCreationTime = op.get(DATABASE_TIMEOUT_MINUTES, TimeUnit.MINUTES).getCreateTime();
        // TODO: Change this to greaterThan when the create time of a database is reported back by
        // the server.
        assertTrue(secondCreationTime.compareTo(initialDbCreateTime) >= 0);
        // Assert that the CreateDatabase RPC was called only once, and that the operation tracking
        // was resumed through a GetOperation call.
        assertEquals(1, createDbInterceptor.methodCount.get());
        assertTrue(createDbInterceptor.getOperationCount.get() >= 1);
    }
}
Also used : Backup(com.google.cloud.spanner.Backup) ArrayList(java.util.ArrayList) Stopwatch(com.google.common.base.Stopwatch) Timestamp(com.google.cloud.Timestamp) SpannerOptions(com.google.cloud.spanner.SpannerOptions) Random(java.util.Random) Database(com.google.cloud.spanner.Database) CreateBackupMetadata(com.google.spanner.admin.database.v1.CreateBackupMetadata) DatabaseAdminClient(com.google.cloud.spanner.DatabaseAdminClient) RestoreDatabaseMetadata(com.google.spanner.admin.database.v1.RestoreDatabaseMetadata) SpannerException(com.google.cloud.spanner.SpannerException) CreateDatabaseMetadata(com.google.spanner.admin.database.v1.CreateDatabaseMetadata) ExecutionException(java.util.concurrent.ExecutionException) Spanner(com.google.cloud.spanner.Spanner) Test(org.junit.Test) SlowTest(com.google.cloud.spanner.SlowTest)

Example 32 with Database

use of com.google.spanner.admin.database.v1.Database in project java-spanner by googleapis.

the class SpannerSample method listDatabaseOperations.

// [END spanner_list_backup_operations]
// [START spanner_list_database_operations]
static void listDatabaseOperations(InstanceAdminClient instanceAdminClient, DatabaseAdminClient dbAdminClient, InstanceId instanceId) {
    Instance instance = instanceAdminClient.getInstance(instanceId.getInstance());
    // Get optimize restored database operations.
    Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert(TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, TimeUnit.HOURS), 0);
    String filter = String.format("(metadata.@type:type.googleapis.com/" + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " + "(metadata.progress.start_time > \"%s\")", last24Hours);
    for (Operation op : instance.listDatabaseOperations(Options.filter(filter)).iterateAll()) {
        try {
            OptimizeRestoredDatabaseMetadata metadata = op.getMetadata().unpack(OptimizeRestoredDatabaseMetadata.class);
            System.out.println(String.format("Database %s restored from backup is %d%% optimized", metadata.getName(), metadata.getProgress().getProgressPercent()));
        } catch (InvalidProtocolBufferException e) {
            // The returned operation does not contain OptimizeRestoredDatabaseMetadata.
            System.err.println(e.getMessage());
        }
    }
}
Also used : Instance(com.google.cloud.spanner.Instance) OptimizeRestoredDatabaseMetadata(com.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Operation(com.google.longrunning.Operation) Timestamp(com.google.cloud.Timestamp)

Example 33 with Database

use of com.google.spanner.admin.database.v1.Database in project java-spanner by googleapis.

the class SpannerSample method restoreBackup.

// [END spanner_list_backups]
// [START spanner_restore_backup]
static void restoreBackup(DatabaseAdminClient dbAdminClient, BackupId backupId, DatabaseId sourceDatabaseId, DatabaseId restoreToDatabase) {
    Backup backup = dbAdminClient.newBackupBuilder(backupId).build();
    // Initiate the request which returns an OperationFuture.
    System.out.println(String.format("Restoring backup [%s] to database [%s]...", backup.getId().toString(), restoreToDatabase.toString()));
    try {
        OperationFuture<Database, RestoreDatabaseMetadata> op = backup.restore(restoreToDatabase);
        // Wait until the database has been restored.
        Database db = op.get();
        // Refresh database metadata and get the restore info.
        RestoreInfo restore = db.reload().getRestoreInfo();
        Timestamp versionTime = Timestamp.fromProto(restore.getProto().getBackupInfo().getVersionTime());
        System.out.println("Restored database [" + restore.getSourceDatabase().getName() + "] from [" + restore.getBackup().getName() + "] with version time [" + versionTime + "]");
    } catch (ExecutionException e) {
        throw SpannerExceptionFactory.newSpannerException(e.getCause());
    } catch (InterruptedException e) {
        throw SpannerExceptionFactory.propagateInterrupt(e);
    }
}
Also used : RestoreInfo(com.google.cloud.spanner.RestoreInfo) Backup(com.google.cloud.spanner.Backup) Database(com.google.cloud.spanner.Database) RestoreDatabaseMetadata(com.google.spanner.admin.database.v1.RestoreDatabaseMetadata) ExecutionException(java.util.concurrent.ExecutionException) Timestamp(com.google.cloud.Timestamp)

Example 34 with Database

use of com.google.spanner.admin.database.v1.Database in project java-spanner by googleapis.

the class RestoreBackupWithEncryptionKey method restoreBackupWithEncryptionKey.

static Void restoreBackupWithEncryptionKey(DatabaseAdminClient adminClient, String projectId, String instanceId, String backupId, String restoreId, String kmsKeyName) {
    final Restore restore = adminClient.newRestoreBuilder(BackupId.of(projectId, instanceId, backupId), DatabaseId.of(projectId, instanceId, restoreId)).setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)).build();
    final OperationFuture<Database, RestoreDatabaseMetadata> operation = adminClient.restoreDatabase(restore);
    Database database;
    try {
        System.out.println("Waiting for operation to complete...");
        database = operation.get();
    } catch (ExecutionException e) {
        // If the operation failed during execution, expose the cause.
        throw SpannerExceptionFactory.asSpannerException(e.getCause());
    } catch (InterruptedException e) {
        // and the thread is interrupted, either before or during the activity.
        throw SpannerExceptionFactory.propagateInterrupt(e);
    }
    System.out.printf("Database %s restored to %s from backup %s using encryption key %s%n", database.getRestoreInfo().getSourceDatabase(), database.getId(), database.getRestoreInfo().getBackup(), database.getEncryptionConfig().getKmsKeyName());
    return null;
}
Also used : Database(com.google.cloud.spanner.Database) RestoreDatabaseMetadata(com.google.spanner.admin.database.v1.RestoreDatabaseMetadata) ExecutionException(java.util.concurrent.ExecutionException) Restore(com.google.cloud.spanner.Restore)

Example 35 with Database

use of com.google.spanner.admin.database.v1.Database in project java-spanner by googleapis.

the class SpannerSample method createBackup.

// [END spanner_query_with_query_options]
// [START spanner_create_backup]
static void createBackup(DatabaseAdminClient dbAdminClient, DatabaseId databaseId, BackupId backupId, Timestamp versionTime) {
    // Set expire time to 14 days from now.
    Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS));
    Backup backup = dbAdminClient.newBackupBuilder(backupId).setDatabase(databaseId).setExpireTime(expireTime).setVersionTime(versionTime).build();
    // Initiate the request which returns an OperationFuture.
    System.out.println("Creating backup [" + backup.getId() + "]...");
    OperationFuture<Backup, CreateBackupMetadata> op = backup.create();
    try {
        // Wait for the backup operation to complete.
        backup = op.get();
        System.out.println("Created backup [" + backup.getId() + "]");
    } catch (ExecutionException e) {
        throw (SpannerException) e.getCause();
    } catch (InterruptedException e) {
        throw SpannerExceptionFactory.propagateInterrupt(e);
    }
    // Reload the metadata of the backup from the server.
    backup = backup.reload();
    System.out.println(String.format("Backup %s of size %d bytes was created at %s for version of database at %s", backup.getId().getName(), backup.getSize(), LocalDateTime.ofEpochSecond(backup.getProto().getCreateTime().getSeconds(), backup.getProto().getCreateTime().getNanos(), OffsetDateTime.now().getOffset()), LocalDateTime.ofEpochSecond(backup.getProto().getVersionTime().getSeconds(), backup.getProto().getVersionTime().getNanos(), OffsetDateTime.now().getOffset())));
}
Also used : Backup(com.google.cloud.spanner.Backup) CreateBackupMetadata(com.google.spanner.admin.database.v1.CreateBackupMetadata) ExecutionException(java.util.concurrent.ExecutionException) Timestamp(com.google.cloud.Timestamp)

Aggregations

Test (org.junit.Test)53 CreateDatabaseMetadata (com.google.spanner.admin.database.v1.CreateDatabaseMetadata)32 Database (com.google.cloud.spanner.Database)31 ArrayList (java.util.ArrayList)25 AbstractMessage (com.google.protobuf.AbstractMessage)24 ExecutionException (java.util.concurrent.ExecutionException)22 Database (com.google.spanner.admin.database.v1.Database)21 Operation (com.google.longrunning.Operation)18 ByteString (com.google.protobuf.ByteString)16 DatabaseAdminClient (com.google.cloud.spanner.DatabaseAdminClient)13 SpannerException (com.google.cloud.spanner.SpannerException)12 Database (org.molgenis.emx2.Database)12 CreateBackupMetadata (com.google.spanner.admin.database.v1.CreateBackupMetadata)11 DatabaseName (com.google.spanner.admin.database.v1.DatabaseName)10 RestoreDatabaseMetadata (com.google.spanner.admin.database.v1.RestoreDatabaseMetadata)9 Timestamp (com.google.cloud.Timestamp)8 Spanner (com.google.cloud.spanner.Spanner)8 RestoreDatabaseRequest (com.google.spanner.admin.database.v1.RestoreDatabaseRequest)7 UpdateDatabaseDdlMetadata (com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata)7 StatusRuntimeException (io.grpc.StatusRuntimeException)7