We have a script that runs multiple generated Apex lines and pipes them through sfdx force:apex:execute. This has, historically, worked beautifully, however today when I revisited those scripts, they no longer exit out of sfdx after completing successfully, which blocks the rest of our script execution.
Two ways:
echo "System.debug('Hello');" | sfdx force:apex:executeOR
sfdx force:apex:execute, type a line and hit CTRL-D to trigger executionAnonymous code executes (or returns an error) and then exits back to the command line
Anonymous code executes (or returns an error) and hangs, requiring the user to hit CTRL-C to Terminate batch job (Y/N)? - which then terminates the calling shell script that had been blocked.
EDIT Part of this is impatience. It DOES finally exit out after about a minute, however before it was virtually instantaneous.
$ echo "System.debug('Hello');" | sfdx force:apex:execute
Start typing Apex code. Press the Enter key after each line, then press CTRL+D when finished.
System.debug('Hello');
Compiled successfully.
Executed successfully.
49.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO
Execute Anonymous: System.debug('Hello');
13:38:41.32 (32245668)|USER_INFO|[EXTERNAL]|00517000006dgbw|[email protected]|(GMT-07:00) Pacific Daylight Time (America/Los_Angeles)|GMT-07:00
13:38:41.32 (32302825)|EXECUTION_STARTED
13:38:41.32 (32314888)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex
13:38:41.32 (33034465)|USER_DEBUG|[1]|DEBUG|Hello
13:38:41.33 (33142154)|CUMULATIVE_LIMIT_USAGE
13:38:41.33 (33142154)|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
13:38:41.33 (33142154)|CUMULATIVE_LIMIT_USAGE_END
13:38:41.32 (33220220)|CODE_UNIT_FINISHED|execute_anonymous_apex
13:38:41.32 (33233918)|EXECUTION_FINISHED
^CTerminate batch job (Y/N)?
SFDX CLI Version
sfdx-cli/7.75.1-5585088c75 win32-x64 node-v12.18.3
SFDX plugin Version
@oclif/plugin-autocomplete 0.1.5 (core)
@oclif/plugin-commands 1.3.0 (core)
@oclif/plugin-not-found 1.2.4 (core)
@oclif/plugin-plugins 1.9.0 (core)
@oclif/plugin-warn-if-update-available 1.7.0 (core)
@oclif/plugin-which 1.0.3 (core)
@salesforce/lwc-dev-server 2.5.1
鈹溾攢 @oclif/plugin-help 2.2.3
鈹斺攢 @oclif/plugin-update 1.3.9
@salesforce/sfdx-plugin-lwc-test 0.1.7
@salesforce/sfdx-trust 3.4.3 (core)
alias 1.1.2 (core)
analytics 1.12.1 (core)
config 1.1.8 (core)
generator 1.1.3 (core)
salesforcedx 49.13.1
鈹溾攢 templates 49.4.4
鈹溾攢 custom-metadata 1.0.10
鈹溾攢 salesforce-alm 49.12.2
鈹斺攢 apex 0.1.1
sfdx-cli 7.75.1 (core)
OS and version:
Windows 10, using primarily Git Bash in Visual Studio Code's Terminal window, but also occurs in normal Command Prompt
One of my colleagues on Mac verified that this bug occurs for them as well with the latest sfdx, so it is sadly not a Windows-only issue.
The root cause is because of the new timeout in module @salesforce/apex-node executeService.js. In getUserInput() there is a timeout of 60 seconds on the readInterface. This timeout is not closed when the readInterface sends a close event, so the awaiter is waiting for the timeout to complete.
If you add timeout.close(); after resole(apexCode); then the bug reported here goes away. This timeout did not exist in the original implementation that was in salesforce-alm hence why it was not an issue before
// apex-node/../executeService.js getUserInput()
readInterface.on('close', () => {
resolve(apexCode);
timeout.close(); // add me!
});
A workaround is to write to an intermediate file:
echo "System.debug('Hello');" > throwaway.apex
sfdx force:apex:execute -f throwaway.apex
Most helpful comment
The root cause is because of the new timeout in module
@salesforce/apex-nodeexecuteService.js. IngetUserInput()there is a timeout of 60 seconds on thereadInterface. This timeout is not closed when thereadInterfacesends a close event, so the awaiter is waiting for the timeout to complete.If you add
timeout.close();afterresole(apexCode);then the bug reported here goes away. This timeout did not exist in the original implementation that was insalesforce-almhence why it was not an issue before