diff --git a/packages/apex-node/src/execute/executeService.ts b/packages/apex-node/src/execute/executeService.ts index e2d9d394..9c475209 100644 --- a/packages/apex-node/src/execute/executeService.ts +++ b/packages/apex-node/src/execute/executeService.ts @@ -5,7 +5,6 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import { Connection } from '@salesforce/core'; -import { JsonCollection } from '@salesforce/ts-types'; import { existsSync, readFileSync } from 'fs'; import { ExecuteAnonymousResponse, @@ -18,6 +17,7 @@ import { action } from './types'; import { nls } from '../i18n'; +import { refreshAuth } from '../utils'; import { encodeBody } from './utils'; import * as readline from 'readline'; @@ -45,7 +45,7 @@ export class ExecuteService { e.message && e.message.includes('INVALID_SESSION_ID') ) { - await this.refreshAuth(this.connection); + await refreshAuth(this.connection); count += 1; } else { throw new Error( @@ -160,15 +160,9 @@ export class ExecuteService { return formattedResponse; } - // TODO: make these general utils accessible to other classes public async connectionRequest( requestData: RequestData ): Promise { return (await this.connection.request(requestData)) as SoapResponse; } - - public async refreshAuth(connection: Connection): Promise { - const requestInfo = { url: connection.baseUrl(), method: 'GET' }; - return await connection.request(requestInfo); - } } diff --git a/packages/apex-node/src/streaming/streamingClient.ts b/packages/apex-node/src/streaming/streamingClient.ts index 64467afa..f96569ef 100644 --- a/packages/apex-node/src/streaming/streamingClient.ts +++ b/packages/apex-node/src/streaming/streamingClient.ts @@ -6,10 +6,11 @@ */ import { Client as FayeClient } from 'faye'; -import { Connection, Org } from '@salesforce/core'; -import { ApexTestQueueItem, ApexTestQueueItemStatus } from '../tests/types'; +import { Connection } from '@salesforce/core'; import { StreamMessage, TestResultMessage } from './types'; import { nls } from '../i18n'; +import { refreshAuth } from '../utils'; +import { ApexTestQueueItem, ApexTestQueueItemStatus } from '../tests/types'; const TEST_RESULT_CHANNEL = '/systemTopic/TestResult'; const DEFAULT_STREAMING_TIMEOUT_MS = 14400; @@ -73,10 +74,10 @@ export class StreamingClient { }); } + // NOTE: There's an intermittent auth issue with Streaming API that requires the connection to be refreshed + // The builtin org.refreshAuth() util only refreshes the connection associated with the instance of the org you provide, not all connections associated with that username's orgs public async init(): Promise { - const username = this.conn.getUsername(); - const org = await Org.create({ aliasOrUsername: username }); - await org.refreshAuth(); + await refreshAuth(this.conn); const accessToken = this.conn.getConnectionOptions().accessToken; if (accessToken) { diff --git a/packages/apex-node/src/utils/authUtil.ts b/packages/apex-node/src/utils/authUtil.ts new file mode 100644 index 00000000..89d395c1 --- /dev/null +++ b/packages/apex-node/src/utils/authUtil.ts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { Connection } from '@salesforce/core'; +import { JsonCollection } from '@salesforce/ts-types'; + +export async function refreshAuth( + connection: Connection +): Promise { + const requestInfo = { url: connection.baseUrl(), method: 'GET' }; + return await connection.request(requestInfo); +} diff --git a/packages/apex-node/src/utils/index.ts b/packages/apex-node/src/utils/index.ts index 83e8698b..74d7ac96 100644 --- a/packages/apex-node/src/utils/index.ts +++ b/packages/apex-node/src/utils/index.ts @@ -9,3 +9,4 @@ export { createFile } from './fileSystemHandler'; export { CommonOptions } from './types'; export { Column, Row, Table } from './table'; export { getCurrentTime, formatStartTime, msToSecond } from './dateUtil'; +export { refreshAuth } from './authUtil'; diff --git a/packages/apex-node/test/execute/executeService.test.ts b/packages/apex-node/test/execute/executeService.test.ts index ad76ed95..d75ef0b8 100644 --- a/packages/apex-node/test/execute/executeService.test.ts +++ b/packages/apex-node/test/execute/executeService.test.ts @@ -201,7 +201,6 @@ describe('Apex Execute Tests', async () => { ExecuteService.prototype, 'connectionRequest' ); - sandboxStub.stub(ExecuteService.prototype, 'refreshAuth'); const error = new Error('INVALID_SESSION_ID'); error.name = 'ERROR_HTTP_500'; connRequestStub.onFirstCall().throws(error); diff --git a/packages/apex-node/test/streaming/streamingClient.test.ts b/packages/apex-node/test/streaming/streamingClient.test.ts index d4e4db88..3979460f 100644 --- a/packages/apex-node/test/streaming/streamingClient.test.ts +++ b/packages/apex-node/test/streaming/streamingClient.test.ts @@ -88,6 +88,16 @@ describe('Streaming API Client', () => { } }); + it('should force refresh the connection during init', async () => { + const requestStub = sandboxStub + .stub(mockConnection, 'baseUrl') + .returns('66568xxxx'); + + const streamClient = new StreamingClient(mockConnection); + await streamClient.init(); + expect(requestStub.calledOnce).to.be.true; + }); + it('should disconnect when subscribe throws an error', async () => { const stubSubscribe = sandboxStub .stub(FayeClient.prototype, 'subscribe')