Skip to content

Commit

Permalink
Reduced logging for cache decorator.
Browse files Browse the repository at this point in the history
Fix issue with refresh datapack command.
Ensure production Salesforce metadata deployments always use checkOnly flag.
  • Loading branch information
Codeneos committed Feb 19, 2020
1 parent 3baf5c9 commit 834292d
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 27 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog Vlocity Salesforce Integration for VSCode

## [0.12.13] - 2019-02-19
- Fix refresh datapack error
- More logging for Salesforce deployments
- Force all production deployment requests to check only

## [0.12.12] - 2019-02-19
- Auto create and delete `-meta.xml` files for classes
- Auto create boiler plate code for APEX classes and interfaces
Expand Down
36 changes: 25 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vlocode",
"displayName": "Salesforce Vlocity Integration",
"description": "Salesforce and Vlocity development and deployment extension for VSCode",
"version": "0.12.12",
"version": "0.12.13",
"license": "MIT",
"icon": "resources/icon.png",
"author": {
Expand Down
43 changes: 35 additions & 8 deletions src/services/salesforceService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ export default class SalesforceService implements JsForceConnectionProvider {
const packageXml = new PackageXml(manifest.apiVersion || '45.0');
const packageZip = new ZipArchive();

// Log
this.logger.verbose(`Building metadata ZIP package API ${packageXml.version}`);

for (const [packagePath, info] of Object.entries(manifest.files)) {
// Stop directly and return null
if (token && token.isCancellationRequested) {
Expand Down Expand Up @@ -424,6 +427,8 @@ export default class SalesforceService implements JsForceConnectionProvider {
const mdPackage : MetadataManifest = { files: {} };
const metaFiles = await getMetaFiles(files.map(file => file.fsPath), true);

this.logger.verbose(`Building package manifest for ${files.length} selected files/folders`);

// Build zip archive for all expanded files
// Note use posix path separators when building package.zip
for (const metaFile of metaFiles) {
Expand Down Expand Up @@ -594,6 +599,7 @@ export default class SalesforceService implements JsForceConnectionProvider {
private async deploy(zipInput: Stream | Buffer | string | ZipArchive, options?: jsforce.DeployOptions, progress?: DeploymentProgress, token?: vscode.CancellationToken) : Promise<DetailedDeployResult> {
const startTime = new Date().getTime();
const checkInterval = 500;
const logInterval = 5000;
const deploymentTypeText = options && options.checkOnly ? 'Validate' : 'Deploy';

const deploymentTask = async (progress: DeploymentProgress, cancellationToken: vscode.CancellationToken) => {
Expand All @@ -608,36 +614,57 @@ export default class SalesforceService implements JsForceConnectionProvider {
});
}

// Start deploy
const connection = await this.getJsForceConnection();
const deployJob = await connection.metadata.deploy(zipInput, {
// Set deploy options passed to JSforce; options arg can override the defaults
const deployOptions = {
singlePackage: true,
performRetrieve: true,
ignoreWarnings: false,
ignoreWarnings: true,
autoUpdatePackage: false,
allowMissingFiles: false,
// We asssume we only run on developer orgs, as such set these options to true by default
// We assume we only run on developer orgs by default
purgeOnDelete: true,
rollbackOnError: false,
...options
});
};

if (await this.isProductionOrg()) {
this.logger.warn(`Production deployment detected; running as validate/checkOnly`);
// Always check only for production
deployOptions.rollbackOnError = true;
deployOptions.purgeOnDelete = false;
deployOptions.checkOnly = true;
}

// Start deploy
const connection = await this.getJsForceConnection();
const deployJob = await connection.metadata.deploy(zipInput, deployOptions);

// Wait for deploy
let lastConsoleLog = 0;
while (await wait(checkInterval)) {
if (cancellationToken && cancellationToken.isCancellationRequested) {
// Cancel deployment; we don't really care if the cancel is successfull or not
// Cancel deployment; we don't really care if the cancel is successfully or not
(<any>connection.metadata).cancelDeploy(deployJob.id);
throw new Error(`${deploymentTypeText} cancelled`);
}

const status = await connection.metadata.checkDeployStatus(deployJob.id, true);

if (Date.now() - lastConsoleLog > logInterval) {
// do not create seperate interval for logging but use the main status check loop
this.logger.info(
`Deployment ${status.id} - ${status.status} ` +
`(${status.numberComponentsDeployed ?? 0}/${status.numberComponentsTotal ?? 0})`);
lastConsoleLog = Date.now();
}

if (status.done) {
const details : any = status.details;
if (details.componentFailures && !Array.isArray(details.componentFailures)) {
details.componentFailures = [ details.componentFailures ];
}
return status;
}
}
}
};

Expand Down
8 changes: 4 additions & 4 deletions src/services/vlocityMatchingKeyService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export default class VlocityMatchingKeyService {

//private matchingKeys = new Lazy(() => this.loadAllMatchingKeys());
private readonly matchingKeyQuery = new QueryBuilder('vlocity_namespace__DRMatchingKey__mdt')
.select('Name', 'vlocity_namespace__MatchingKeyFields__c', 'vlocity_namespace__ObjectAPIName__c', 'vlocity_namespace__ReturnKeyField__c')
.select('Label', 'vlocity_namespace__MatchingKeyFields__c', 'vlocity_namespace__ObjectAPIName__c', 'vlocity_namespace__ReturnKeyField__c')
.build();
private readonly datapackConfigQuery = new QueryBuilder('vlocity_namespace__VlocityDataPackConfiguration_mdt')
.select('Name', 'vlocity_namespace__PrimarySObjectType__c')
private readonly datapackConfigQuery = new QueryBuilder('vlocity_namespace__VlocityDataPackConfiguration__mdt')
.select('Label', 'vlocity_namespace__PrimarySObjectType__c')
.build();

constructor(
Expand Down Expand Up @@ -145,7 +145,7 @@ export default class VlocityMatchingKeyService {
const matchingKeyObjects = matchingKeyResults.map(record => {
return {
sobjectType: record.ObjectAPIName__c,
datapackType: this.getDatapackType(record.ObjectAPIName__c) ?? record.Name,
datapackType: this.getDatapackType(record.ObjectAPIName__c) ?? record.Label,
fields: record.MatchingKeyFields__c.split(',').map(s => s.trim()),
returnField: record.ReturnKeyField__c
};
Expand Down
6 changes: 3 additions & 3 deletions src/util/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,20 @@ export default function cache(ttl: number = 60) {
const key = args.reduce((checksum, arg) => checksum + (arg?.toString() ?? ''), name);
const cachedValue = cache.get(key);
if (cachedValue) {
logger().verbose(`Cache HIT -> ${name}`);
logger().debug(`Load response from cache -> ${name}`);
return cachedValue;
}
// Exceptions cause
const newValue = originalMethod.apply(this, args);
if (ttl > 0) {
setTimeout(() => cache.delete(key), ttl * 1000);
}
logger().verbose(`Cache MISS -> ${name}`);
logger().debug(`Cache miss, retrieve value from source -> ${name}`);
cache.set(key, newValue);
if (isPromise(newValue)) {
// Remove invalid results from the cache
newValue.catch(err => {
logger().verbose(`Cache exception -> ${name}`);
logger().debug(`Delete cached promise on exception -> ${name}`);
cache.delete(key);
// Rethrow the exceptions so the original handler can handle it
throw err;
Expand Down

0 comments on commit 834292d

Please sign in to comment.