Skip to content

Commit

Permalink
tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
fredzqm committed May 10, 2024
1 parent e65a582 commit 0601f00
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 42 deletions.
3 changes: 2 additions & 1 deletion src/dataconnect/client.ts
Expand Up @@ -80,8 +80,9 @@ export async function deleteService(
locationId: string,
serviceId: string,
): Promise<types.Service> {
// NOTE(fredzqm): Don't force delete yet. Backend would leave orphaned resources.
const op = await dataconnectClient().delete<types.Service>(
`projects/${projectId}/locations/${locationId}/services/${serviceId}?force=true`,
`projects/${projectId}/locations/${locationId}/services/${serviceId}`,
);
const pollRes = await operationPoller.pollOperation<types.Service>({
apiOrigin: dataconnectOrigin(),
Expand Down
20 changes: 5 additions & 15 deletions src/dataconnect/provisionCloudSql.ts
Expand Up @@ -77,21 +77,11 @@ export async function provisionCloudSql(args: {
try {
await cloudSqlAdminClient.getDatabase(projectId, instanceId, databaseId);
silent || utils.logLabeledBullet("dataconnect", `Found existing database ${databaseId}.`);
} catch (err: any) {
if (err.status === 404) {
// Create the database if not found.
silent ||
utils.logLabeledBullet(
"dataconnect",
`Database ${databaseId} not found, creating it now...`,
);
await cloudSqlAdminClient.createDatabase(projectId, instanceId, databaseId);
silent || utils.logLabeledBullet("dataconnect", `Database ${databaseId} created.`);
} else {
// Skip it if the database is not accessible.
// Possible that the CSQL instance is in the middle of something.
silent || utils.logLabeledWarning("dataconnect", `Database ${databaseId} is not accessible.`);
}
} catch (err) {
silent ||
utils.logLabeledBullet("dataconnect", `Database ${databaseId} not found, creating it now...`);
await cloudSqlAdminClient.createDatabase(projectId, instanceId, databaseId);
silent || utils.logLabeledBullet("dataconnect", `Database ${databaseId} created.`);
}
if (enableGoogleMlIntegration) {
await grantRolesToCloudSqlServiceAccount(projectId, instanceId, [GOOGLE_ML_INTEGRATION_ROLE]);
Expand Down
69 changes: 47 additions & 22 deletions src/dataconnect/schemaMigration.ts
Expand Up @@ -12,13 +12,24 @@ import { FirebaseError } from "../error";
import { needProjectId } from "../projectUtils";
import { logLabeledBullet, logLabeledWarning, logLabeledSuccess } from "../utils";
import * as errors from "./errors";
import { Message } from '@google-cloud/pubsub';

Check failure on line 15 in src/dataconnect/schemaMigration.ts

View workflow job for this annotation

GitHub Actions / unit (18)

'Message' is defined but never used

Check failure on line 15 in src/dataconnect/schemaMigration.ts

View workflow job for this annotation

GitHub Actions / unit (18)

Replace `'@google-cloud/pubsub'` with `"@google-cloud/pubsub"`

Check failure on line 15 in src/dataconnect/schemaMigration.ts

View workflow job for this annotation

GitHub Actions / lint (20)

'Message' is defined but never used

Check failure on line 15 in src/dataconnect/schemaMigration.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Replace `'@google-cloud/pubsub'` with `"@google-cloud/pubsub"`

Check failure on line 15 in src/dataconnect/schemaMigration.ts

View workflow job for this annotation

GitHub Actions / unit (18)

'Message' is defined but never used

Check failure on line 15 in src/dataconnect/schemaMigration.ts

View workflow job for this annotation

GitHub Actions / unit (18)

Replace `'@google-cloud/pubsub'` with `"@google-cloud/pubsub"`

export async function diffSchema(schema: Schema): Promise<Diff[]> {
const { serviceName, instanceName, databaseId } = getIdentifiers(schema);
await ensureServiceIsConnectedToCloudSql(serviceName, instanceName, databaseId);
await ensureServiceIsConnectedToCloudSql(
serviceName,
instanceName,
databaseId,
/* linkIfNotConnected=*/ false,
);
try {
await upsertSchema(schema, /** validateOnly=*/ true);
logLabeledSuccess("dataconnect", `Database schema is up to date.`);
} catch (err: any) {
if (err.status !== 400) {
throw err;
}
// Display failed precondition errors nicely.
const invalidConnectors = errors.getInvalidConnectors(err);
if (invalidConnectors.length) {
displayInvalidConnectors(invalidConnectors);
Expand All @@ -29,7 +40,6 @@ export async function diffSchema(schema: Schema): Promise<Diff[]> {
return incompatible.diffs;
}
}
logLabeledSuccess("dataconnect", `Database schema is up to date.`);
return [];
}

Expand All @@ -42,11 +52,20 @@ export async function migrateSchema(args: {
const { options, schema, allowNonInteractiveMigration, validateOnly } = args;

const { serviceName, instanceId, instanceName, databaseId } = getIdentifiers(schema);
await ensureServiceIsConnectedToCloudSql(serviceName, instanceName, databaseId);
await ensureServiceIsConnectedToCloudSql(
serviceName,
instanceName,
databaseId,
/* linkIfNotConnected=*/ true,
);
try {
await upsertSchema(schema, validateOnly);
logger.debug(`Database schema was up to date for ${instanceId}:${databaseId}`);
} catch (err: any) {
if (err.status !== 400) {
throw err;
}
// Parse and handle failed precondition errors, then retry.
const incompatible = errors.getIncompatibleSchemaError(err);
const invalidConnectors = errors.getInvalidConnectors(err);
if (!incompatible && !invalidConnectors.length) {
Expand Down Expand Up @@ -266,37 +285,43 @@ function displayInvalidConnectors(invalidConnectors: string[]) {

// If a service has never had a schema with schemaValidation=strict
// (ie when users create a service in console),
// the backend will not have the necesary permissions to check cSQL for differences.
// the backend will not have the necessary permissions to check cSQL for differences.
// We fix this by upserting the currently deployed schema with schemaValidation=strict,
async function ensureServiceIsConnectedToCloudSql(
serviceName: string,
instanceId: string,
databaseId: string,
linkIfNotConnected: boolean,
) {
let currentSchema: Schema;
try {
currentSchema = await getSchema(serviceName);
} catch (err: any) {
if (err.status === 404) {
// If no schema has been deployed yet, deploy an empty one to get connectivity.
currentSchema = {
name: `${serviceName}/schemas/${SCHEMA_ID}`,
source: {
files: [],
},
primaryDatasource: {
postgresql: {
database: databaseId,
cloudSql: {
instance: instanceId,
},
},
},
};
logLabeledBullet("dataconnect", `Linking the Cloud SQL instance...`);
} else {
if (err.status !== 404) {
throw err;
}
if (!linkIfNotConnected) {
logLabeledWarning("dataconnect", `Not yet linked to the Cloud SQL instance.`);
return;
}
// TODO: make this prompt
// Should we upsert service here as well? so `database:sql:migrate` work for new service as well.
logLabeledBullet("dataconnect", `Linking the Cloud SQL instance...`);
// If no schema has been deployed yet, deploy an empty one to get connectivity.
currentSchema = {
name: `${serviceName}/schemas/${SCHEMA_ID}`,
source: {
files: [],
},
primaryDatasource: {
postgresql: {
database: databaseId,
cloudSql: {
instance: instanceId,
},
},
},
};
}
const postgresql = currentSchema.primaryDatasource.postgresql;
if (postgresql?.cloudSql.instance !== instanceId) {
Expand Down
2 changes: 0 additions & 2 deletions src/gcp/cloudsql/cloudsqladmin.ts
Expand Up @@ -51,8 +51,6 @@ export async function createInstance(
userLabels: { "firebase-data-connect": "ft" },
insightsConfig: {
queryInsightsEnabled: true,
queryPlansPerMinute: 5, // Match the default settings
queryStringLength: 1024, // Match the default settings
},
},
});
Expand Down
2 changes: 0 additions & 2 deletions src/gcp/cloudsql/types.ts
Expand Up @@ -56,8 +56,6 @@ export interface DatabaseFlag {

interface InsightsConfig {
queryInsightsEnabled: boolean;
queryPlansPerMinute: number;
queryStringLength: number;
}

// TODO: Consider splitting off return only fields and input fields into different types.
Expand Down

0 comments on commit 0601f00

Please sign in to comment.