Terminating a SSIS Foreach loop after x amount of execution time? - sql

I have a collection, which gets executed in the For each loop of the SSIS package. However, i want to ensure that after lets say one hour of executing a particular item, i want the For each loop to terminate or exit. But it should not Stop the execution of that item or Time it out.
Is it possible to achieve ?

It has been quite some time since I've had a good SSIS problem that I've never solved, so thank you for your question.
The approach I came up with requires a Sequence Container that holds a ForEach Loop Container. My Foreach Loop has 6 items in the stack. My requirement is that my loop cannot start any new work after 5 seconds of execution. Inside my loop, I run a 3 second delay in the Execute SQL Task to simulate work. Therefore, a "full" run will take at least 18 seconds (6*3) but if we get the abort working, we'll see 2 total runs.
I have defined 5 variables. You'll notice that in the second column, 2 of those variables are scoped to specific containers. The Second icon in the Variables screen has an arrow -> which is how you change the Scope of a Variable.
The idea is that in the Sequence Container, we're going to use an Expression task to compute the end time. The expression is going to use the System scoped variable ContainerStartTime
#[User::SEQCEndTime] = DATEADD("second", #[User::TaskDuration_s], #[System::ContainerStartTime])
The reason we encapsulate this into a sequence container is there might have been work beforehand that takes 4 seconds to generate a data set for the Loop container and we do not want to be penalized for that work. The formula is driven by the Variable TaskDuration_s which is initialized to 5.
The two SCR Echo Back are just logging messages to the Information stream to "prove" things are working.
The FELC Enum Values has a variable IsLoopValid defined in it. This expression is
#[User::IsLoopValid] = #[System::ContainerStartTime] < #[User::SEQCEndTime]
Every loop of the ForEach container resets that ContainerStartTime, which is what we want. But if we had evaluated the IsLoopValid in the context of the Sequence container, it'd never change. So, important to have it computed here.
The f/x you see on the precedent constraint between "Set IsLoopValid" and "SQL Do thing" is a non-default constraint because we're going to make it "Expression and Constraint" instead of just "Constraint". The expression is
#[User::IsLoopValid]
Every Loop will compare current time to the max end time (SEQCEndTime) and as long as we have not slipped the boundary, it will go on to the next task. Once we've exceeded the boundary, the Loop container will continue iterating through the result set but since there's no work to be done, it'll finish right quick.
Results
A sample run with the precedent constraint set to just Constraint. We can see the IsLoopValid is flipped to False but since we do not have the Expression in there, it does all 6 loops
SSIS package "C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\SO_73829526.dtsx" starting.
Information: 0x0 at SCR Echo back, SCR Echo Back 0: System::ContainerStartTime->9/23/2022 3:03:49 PM
Information: 0x0 at SCR Echo back, SCR Echo Back 0: User::SEQCEndTime->9/23/2022 3:03:54 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:03:52 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->True
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:03:54 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:03:55 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->True
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:03:54 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:03:59 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->False
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:03:54 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:04:02 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->False
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:03:54 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:04:05 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->False
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:03:54 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:04:08 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->False
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:03:54 PM
SSIS package "C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\SO_73829526.dtsx" finished: Success.
Expression and Constraint
We see the package stop doing the expensive task after 2 loops but does complete successfully.
SSIS package "C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\SO_73829526.dtsx" starting.
Information: 0x0 at SCR Echo back, SCR Echo Back 0: System::ContainerStartTime->9/23/2022 3:05:36 PM
Information: 0x0 at SCR Echo back, SCR Echo Back 0: User::SEQCEndTime->9/23/2022 3:05:41 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:05:39 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->True
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:05:41 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: System::ContainerStartTime->9/23/2022 3:05:42 PM
Information: 0x0 at SCR Echo back, SCR Echo Back: User::IsLoopValid->True
Information: 0x0 at SCR Echo back, SCR Echo Back: User::SEQCEndTime->9/23/2022 3:05:41 PM
SSIS package "C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\SO_73829526.dtsx" finished: Success.

Related

How do I prevent script from crashing as a result of failed proc?

I've got this:
try { run 'tar', '-zxvf', $path.Str, "$dir/META6.json", :err }
Despite being in a try{} block, this line is still causing my script to crash:
The spawned command 'tar' exited unsuccessfully (exit code: 1, signal: 0)
in block at ./all-versions.raku line 27
in block at ./all-versions.raku line 16
in block <unit> at ./all-versions.raku line 13
Why isn't the try{} block allowing the script to continue and how can I get it to continue?
That's because the run didn't fail (yet). run returns a Proc object. And that by itself doesn't throw (yet).
try just returns that Proc object. As soon as the returned value is used however (for instance, by having it sunk), then it will throw.
Compare (with immediate sinking):
$ raku -e 'run "foo"'
The spawned command 'foo' exited unsuccessfully (exit code: 1, signal: 0)
with:
$ raku -e 'my $a = run "foo"; say "ran, going to sink"; $a.sink'
ran, going to sink
The spawned command 'foo' exited unsuccessfully (exit code: 1, signal: 0)
Now, what causes the usage of the Proc object in your code, is unclear. You'd have to show more code.
A way to check for success, is to check the exit-code:
$ raku -e 'my $a = run "foo"; say "failed" if $a.exitcode > 0'
failed
$ raku -e 'my $a = run "echo"; say "failed" if $a.exitcode > 0'
Or alternately, use Jonathan's solution:
$ raku -e 'try sink run "foo"'

How to replace SQL with bash variable of SQL command output

I am working on a program in bash that checks for valid JSON files before loading them into a table. The process first runs f_check_valid_json to verify the JSON. This process runs f_exe_sql_stmnt() that returns a column of bad files, stored in variable bad_fl_list. I would like to be able to input bad_fl_list in the WHERE clause of my update and delete sections of the function.
Right now, the SQL fails when there is more than one JSON file ID in bad_fl_list
f_exe_sql_stmnt(){
db=$1
sql_str=$2
psql -d "$db" -Atc "$sql_str"
if [ $? -gt 0 ]
then
echo "======================================================================="
echo "***Error: Database error while executing sql statement($sql_str)..."
exit 123
fi
}
f_check_valid_json() {
echo "*** checking for valid JSON format***"
sql_stmnt="Select json_fl_id from json_stgng where is_valid_json(json_datarec_fl) = false;"
bad_fl_list=$(f_exe_sql_stmnt "$t_db" "${sql_stmnt}")
echo "BAD FILE LIST: ${bad_fl_list}"
if [ ! -z "$bad_fl_list" ]
then
echo "BAD JSON LIST IS NOT EMPTY"
echo "*** updating balancing table to reflect bad file ***"
updt_bal_log_str="UPDATE ${bal_log_tbl} SET trgt_load_stus_cd ='F' where json_fl_id in ($bad_fl_list);"
f_exe_sql_stmnt "$DB" "$updt_bal_log_str"
echo "*** deleting bad JSON file record from staging with file ID: ${bad_fl_list}"
delete_stmnt="delete from ${stg_tbl} where json_fl_id in ($bad_fl_list);"
f_exe_sql_stmnt "$t_db" "${delete_stmnt}"
fi
}
Here is some example output from the logs:
+ psql -d dedw -Atc 'UPDATE json_load_bal_dtl_log SET trgt_load_stus_cd ='\''F'\'' where json_fl_id in (O21181043417
O21181043417
O21181003641);'
ERROR: syntax error at or near "O21181043417"
LINE 2: O21181043417
^

Run sql query from If else block in shell script

I want to connect sql db and execute sql query from shell script. I tried using this
if float_cmp "$size1 > 7.50"; then
echo "### THE DATA SIZE IS GREATER THAN 7.5 GB ###"
echo "############### DROPPING CREATED $IMPUSER USER ###########################"
${PATH_TO_CLIENT}sqlplus $EXPUSER/$EXPPWD#$ENDPOINT<< EOF
drop user $IMPUSER cascade;
exit;
EOF
exit 1
else
echo "### THE DATA SIZE IS OKAY ###"
fi
The statement is working outside if block but throwing error when executing in IF block
line 80: warning: here-document at line 72 delimited by end-of-file (wanted `EOF')
line 81: syntax error: unexpected end of file
Can anyone please tell what am I doing wrong and what is the solution?
Try removing the indentation inside of the here-document:
if float_cmp "$size1 > 7.50"; then
echo "### THE DATA SIZE IS GREATER THAN 7.5 GB ###"
echo "############### DROPPING CREATED $IMPUSER USER ###########################"
"${PATH_TO_CLIENT}"sqlplus $EXPUSER/$EXPPWD#$ENDPOINT<< EOF
drop user $IMPUSER cascade;
exit;
EOF
exit 1
else
echo "### THE DATA SIZE IS OKAY ###"
fi

How to formulate a Batch script if else clause

I have a simple test to tell me if tomcat8 is running or not. It simply outputs if the service is found or not.
net start | find "Tomcat8" > nul 2>&1
if %ERRORLEVEL%==0 echo "Tomcat8 is running"
if %ERRORLEVEL%==1 echo "Tomcat8 not running"
How could I actually integrate this into a function so I could first test if tomcat8 is running, and if yes - goto end:, and if not - start the service?
eg.
Read if /?:
%ERRORLEVEL% will expand into a string representation of the current
value of ERRORLEVEL, provided that there is not already an
environment variable with the name ERRORLEVEL, in which case you
will get its value instead. After running a program, the following
illustrates ERRORLEVEL use:
goto answer%ERRORLEVEL%
:answer0
echo Program had return code 0
:answer1
echo Program had return code 1
Unfortunately, above code snippet seems to be a bit confusing as displays both messages in case of errorlevel 0. Try next (combined with find return codes):
net start | find "Tomcat8" > nul 2>&1
goto answer%ERRORLEVEL%
:answer0
echo `find` had return code 0, Tomcat8 is running
goto :acorp
:answer1
echo `find` had return code 1, Tomcat8 not running
rem code snippet to start the service here
goto :acorp
:answer2
rem dummy/debugging
echo `find` had return code 2: invalid switch is given
pause
:acorp
Another approach: IF… ELSE …
Parenthesis can be used to split commands across multiple lines. This
enables writing more complex IF… ELSE… commands:
IF EXIST filename.txt (
Echo deleting filename.txt
Del filename.txt
) ELSE (
Echo The file was not found.
)
When using parenthesis the CMD shell will expand [read] all the
variables at the beginning of the code block and use those values even
if the variables value has just been changed. Turning on
DelayedExpansion will force the shell to read variables at the
start of every line.
net start | find "Tomcat8" > nul 2>&1
if %ERRORLEVEL%==1 (
echo "Tomcat8 not running"
rem code snippet to start the service here
) else (
echo "Tomcat8 is running"
)

Why is systemtap not generating the output necessary for flamegraph creation?

When executing stap for the purposes of generating flamegraph data, why is my out.stap-stacks missing process data?
OS: RHEL 5.10.0.2
Kernel: 2.6.18-371.11.1.el5
SystemTap: 1.8-6.el5
Packages installed:
systemtap-sdt-devel-1.8-6.el5
systemtap-devel-1.8-6.el5
systemtap-devel-1.8-6.el5
systemtap-runtime-1.8-6.el5
systemtap-sdt-devel-1.8-6.el5
systemtap-1.8-6.el5
systemtap-initscript-1.8-6.el5
systemtap-client-1.8-6.el5
systemtap-server-1.8-6.el5
systemtap-testsuite-1.8-6.el5
kernel-devel-2.6.18-371.11.1.el5
kernel-debug-devel-2.6.18-371.11.1.el5
Command used:
stap -s 32 -D MAXBACKTRACE=100 -D MAXSTRINGLEN=4096 -D MAXMAPENTRIES=10240 \
-D MAXACTION=10000 -D STP_OVERLOAD_THRESHOLD=5000000000 --all-modules \
-ve 'global s; probe timer.profile { s[backtrace()] <<< 1; }
probe end { foreach (i in s+) { print_stack(i);
printf("\t%d\n", #count(s[i])); } } probe timer.s(60) { exit(); }' \
> out.stap-stacks
Sample out.stap-stacks file:
0xffffffff8000e81a
0x0
1
0xffffffff8004ab87
0x0
1
0xffffffff8025d15d
0x0
1
0xffffffff80239356
0x0
1
0xffffffff8004219a
0x0
1
0xffffffff8000ca32
0x0
1
0xffffffff8003214e
0x0
1
0xffffffff80013bc8
0x0
1
0xffffffff80232d41
0x0
1
0xffffffff8001a4ca
0x0
1
0xffffffff80011db5
0x0
1
0xffffffff8004aad2
0x0
1
0xffffffff800ec8bb
0x0
1
0xffffffff8003ead5
0x0
1
0xffffffff80234c43
0x0
The backtrace() function is limited to kernel-space backtraces, and print_stack() maps only kernel-space addresses to symbols. (I cannot explain why the 0xffffffff8* addresses weren't converted to the symbols; maybe some combination of ancient systemtap and ancient kernel?)
If you want to print userspace backtrace data too, you will need to use the u* family of backtrace-related functions.
See also https://sourceware.org/systemtap/examples/#profiling/pf4.stp for a similar script that includes userspace work.