Activiti : Last completed task - sql

Problem
I want to get the last task completed for the process instance. I am able to get the last completed human task, but not a Service task.
What i have tried
I have written a SQL query, i am using MySQL, to find out what is last task that is completed. Here it goes :
SELECT * FROM act_hi_taskinst
where PROC_INST_ID_= '1234' and END_TIME_ IS NOT NULL
order by END_TIME_ desc;
act_hi_taskinst is the table that gets updated as and when the process instance progresses.
The process flow goes something like this :
A human Task (Leave request) -> Service task( Check availability of leave) -> service task(Check feasibility) -> A human task(Manager task)
When the task comes to Manager Task the last completed is Check feasibility, but its not reflecting in database.
Can you please help
Does activiti provide any such API to get the last completed service task? Can you suggest some SQL query to solve the problem.

The information you are looking for is stored in act_hi_actinst table. It contains information about every activity that’s being executed as part of a process instance.
SELECT * FROM act_hi_actinst WHERE proc_inst_id_ = '1929'
AND end_time_ IS NOT NULL ORDER BY end_time_ DESC

Related

How to stop a SQL Agent job (running on an hourly schedule) to stop executing once it is successful

I have a SQL Agent job that runs on the 7th of each month on an hourly basis. I want to stop it from running further once it is successful.
For example, if the job is successful at 8:00 A.M, I dont want it to run any more untill the 7th of next month. Any scripts would be helpful for this.
I am working on trying to establish this rule through the use of MSDB sys.jobs and an idea that I have is to update the Enabled flag to a 0 once the run is complete. Once the 7th of next month hits, another job on the SQL Agent could go in an update the flag back to a 1 so it can be run. i
I suggest you create a new first job-step and, using the answer provided in the question sql-agent-job-last-run-status, you can check if the last execution succeeded.
You can then cancel the job from executing by using exec msdb.dbo.sp_stop_job
I use this method in an Availability group cluster (to check if SQL Agent is running on the primary for jobs the require it) and abort the job if not. It works well.
How about, create a table with a row for last successful run, populate it on a successful run.
Then first thing in the job, check that table, and if the last successful run is since the 7th, terminate.
Otherwise run the rest of the job.
The solution that I finally deployed was to add a step to the job that would disable it once all preceding steps succeeded. I added another job to the Agent that would go and enable this job on the 1st of each month so that they are ready to be executed. Just throwing this out so that someone else can benefit.

Retry Hangfire failed jobs from SQL?

For security or simplicity our Hangfire dashboard UI is not present on production. So we can't just go on and click "Retry". But I'd like to retry some failed jobs manually using SQL. In the DB there are stateid and statename fields. Is it possible to refresh a job by changing its stateid?
I got this idea from the Enqueue function (in SqlServerJobQueue.cs on GitHub) for SQL Server (I'm using postgresql).
insert into hangfire.jobqueue (jobid, queue)
select id, 'default' from hangfire.job where statename = 'Failed';
But it doesn't seem to do anything.

Determine whether to execute SSIS package inside its Control Flow based on whether an SQL Agent job is currently running

How to let an Execute SQL SSIS component decide whether to continue package execution, based on whether a specific SQL Agent job is running.
This is an easy way of letting the package decide to proceed based on whether a specific SQL Agent job is running at the time the package is invoked.
To do so:
Create an Execute SQL task component at the start of your package.
Give it a query that will ask [msdb] on the execution status of the SQL Agent job you are interested in.
Like so:
USE [msdb];
SELECT ISNULL(MAX([sj].[name]),'') AS [JobRunning]
FROM [msdb].[dbo].[sysjobactivity] AS [sja]
INNER JOIN [msdb].[dbo].[sysjobs] AS [sj]
ON [sja].[job_id] = [sj].[job_id]
WHERE [sja].[start_execution_date] IS NOT NULL
AND [sja].[stop_execution_date] IS NULL
AND CAST([sja].[start_execution_date] AS DATE) = CAST(GETDATE() AS DATE)
AND ISNULL([sj].[name],'') LIKE '%NameOfSQLAgentJobThatNeedsToNotBeRunnimg%';
And as shown in the screenshot:
Make sure to set the result set property to single row and to create a Package scoped variable to hold the returned value.
Like so:
And then you need to add the fist step of the Package logic whatever that might be and connect the two.
When you have connected the two, edit the Precedence Constraint and set it to Expression and Constraint and upon Success set the code to:
#[User::JobRunning]!="NameOfSQLAgentJobThatNeedsToNotBeRunnimg"
like so:
And that's it.
Save, build, deploy :)

Locking database rows

I have a table in my database with defined jobs. One of jobs attribute is status, which can be [waiting, in_progress, done]. To process jobs i have defined master-worker relation between two servers, they work in the following way:
master looks for the first record in database with status 'waiting' and triggers a worker server to process the job.
Triggered worker sets status on the job to 'in_progress' in one transaction and starts executing the job (in the meantime server is looking for next job with status 'waiting' and triggers another worker)
when the job is done worker sets status on the job to 'done'
This is the perfect case scenario, however it might happen that during job execution one of the workers dies. In this case job needs to be restarted, however master has no way of verifying if job was done other than checking its status in database ('done'). Therefore if worker dies, in database the job has still status 'in_progress' and server has no idea that worker died and that job needs to be restarted. (we can't get any feedback from worker, we can not ping it and we can not get information what job is he currently working on)
My idea to solve this problem would be:
After worker changed job's status to 'in_progress' (transaction committed) he would open a new transaction with lock on the particular job.
Master, while looking for jobs to start would look for both 'waiting' and 'in_progress' which are not locked
If worker dies, transaction would break, releasing the lock from job record in database and master would reprocess it.
now i'm looking for a way to verify it this would indeed work. Possibly with SQL sctipt in SQL developer (two instances), i would like this to work in the following way:
Instance 1:
open transaction and create a row lock on row_1
sleep for 5 min
release lock
Instance 2:
Open transaction and look for row matching criteria (row_1 and row_2 match criteria)
return selected row
then i would kill instance 1 to simulate worker death and run instance 2 again.
Please advise if my approach is correct
P.S
Also could you point me to some good explanation how can i create script form instance 1?

How to track records in SQL and do some actions if it achieved a specific condition?

Let's say that I have Equipment table and MaintenanceSchedule table in SQL database.
So I need to update the value of the Notification (bit) field in the Equipment table to be true if the Date field in the MaintenanceSchedule table approached.
So, how to track some data stored in the database and do some actions if a specific condition achieved ?
You should probably use a sql job to accomplish this. The problem is you want this process to be resilient in case of failure.
If you just set the flag after the Date field has approached, there are a couple potential bugs. For example, lets say the job doesn't run for some reason. If you run the job on the following day, can you be sure that the flag hasn't been properly set, then unset by the process which does the notification (or whatever processing is done). If you set it again, could it be duplicating work?
It would be best to create a MaintenanceHistory table which logs each time the Notification bit is set. Then you could build a stored procedure to run a job which checks if the Notification bit has been set for a particular Date, and if not, set the bit and log to the history table.
Then you could schedule this as a job which just executes this procedure and set to run at the desired frequency (hourly, daily, monthly, whatever). With this type of implementation, you can run the job as often as you like as it won't re-run for the same Date.
I would create a sql server job to check if the maintenance window aproaches and set the flag accordingly.