An API/Method for Acknowledging a failed job

phavanagi (15 posts)
August 14, 2017 07:16 AM
Accepted Answer

Hi Bill,

Is there an API that would help me acknowledge a job? I was trying to build an UI from where I can possibly call the service so that the job gets acknowledged. Can you let me know more on this.

Thank you!

Bill Staff (599 posts)
August 14, 2017 08:14 AM
Accepted Answer

The ExecutionHistoryItem represents a job instance. Use AcknowledgeStatus to acknowledge a failure (use 0 for the options parameter).

To retrieve the instance, you can use Job.GetHistory or DataContext.GetJobHistory.

phavanagi (15 posts)
August 14, 2017 08:49 AM
Accepted Answer

Hi Bill,

I wrote this code. It does not allow me to create an object of ExecutionHistoryItem, as I don't know what arguments the constructor take. Can you help?

public void acknowledge(string jobname)
{
    ExecutionHistoryItem item = new ExecutionHistoryItem(jobname);
    item.AcknowledgeStatus(0);
}

Bill Staff (599 posts)
August 14, 2017 09:52 AM
Accepted Answer

You cannot create an ExecutionHistoryItem--it represents an instance of the job (an entry in the job history). You do not acknowledge a job; you must acknowledge one or more failed instances. You need to use Job.GetHistory or DataContext.GetJobHistory to get the instance(s) that you want to acknowledge.

So if you want to acknowledge all failed instances for a job with a particular name, you need this:


//code to connect to server and get DataContext omitted

//get the job
var job=context.GetJob("Job Name");

//get all failed instances for the job that have not already been acknowledged
var options=new InstanceQueryParameters();
options.StatusAcknowledged= IncludeExcludeType.Exclude;	//only get unacknowledged instances
options.Statuses.AddRange(JobStatusHelpers.FailureStatuses);	//only get instances with an error status
var instances = job.GetExecutionHistory(options);

//acknowledge the instances
foreach (var instance in instances)
{
	instance.AcknowledgeStatus(0);
}
phavanagi (15 posts)
August 14, 2017 01:00 PM
Accepted Answer
Thanks Bill, great help :)
phavanagi (15 posts)
August 15, 2017 07:55 AM
Accepted Answer

Bill,

Is there a way I can acknowledge only an instance instead of a Job? Probably I Guess I should use chain ID? Can you please let me know more on this ?

Bill Staff (599 posts)
August 15, 2017 08:21 AM
Accepted Answer

As I mentioned above, you never acknowledge a job--always an instance. The code I gave you finds all failed instances for the job and acknowledges them.

A Job object in the API represents a job definition in adTempus. An ExecutionHistoryItem in the API represents an instance of the job (a single execution in the job history).

If you want to acknowledge only a single, specific instance, then you just have to fetch that instance and call Acknowledge (rather than fetching all instances for the job). How you find/fetch that instance depends on what information you have about it. If you are showing a list of instances in your UI and letting the user pick the one to acknowledge, you would use the OID as the key, and fetch it using DataContext.GetObject. The InstanceID is the numeric instance number that is shown to users in the Console. You can find a specific instance number using InstanceQueryParameters.Instances to specify the instance(s) you want when you call GetExecutionHistory.

You'll need to tell me more about what you're trying to do for me to help you more than that.

You would probably not be using the Chain ID to find instances. This is used to link together all related instances when multiple jobs are run in a chain.

phavanagi (15 posts)
August 16, 2017 07:34 AM
Accepted Answer

Hi Bill,

I wish to do something like this :

Passing the instance id from the UI. (generated the JSON from history.OID.AsString; (from the executionHistory). I just want to acknowledge that instance and not all the instances.

public void acknowledge(string instanceId)
  {
      try
         {       
          using (DataContext context = connection.NewDataContext())
                    {
                     OID o = new OID(ClassID.Job, new Guid(jobId));
 
                    Job obj = (Job)context.GetObject(o);
                    
                       Job job = context.GetJob(obj.FullyQualifiedName); // Not sure if we need the job when I provide the instance id
                       var job = context.GetJob(obj.Name);
                        var options = new InstanceQueryParameters();
                        options.StatusAcknowledged = IncludeExcludeType.Exclude;
                        options.Statuses.AddRange(JobStatusHelpers.FailureStatuses);
                         
                         var instance = job.GetExecutionHistory(instanceId); //probably only thing I need if I provide the instance Id
 
                         instance.acknowledge(0);
}
Bill Staff (599 posts)
August 16, 2017 09:35 AM
Accepted Answer

If you have the OID from the instance you want to acknowledge you can just fetch the instance directly:

var oid=new OID(instanceId);
var instance=(ExecutionHistoryItem)context.GetObject(oid);
instance.Acknowledge(0);
phavanagi (15 posts)
August 16, 2017 10:22 AM
Accepted Answer

HI Bill,

I tried this, but its not working. I am not sure if I am generating the correct OID in my JSON data. I am doing the following. I have marked in blue, that is what I am using as the Instance ID. Is that correct? Please let me know.

foreach (var history in execHistoryList)
{
         ExecutionHistoryModel executionHistory = new ExecutionHistoryModel();
         executionHistory.StartTime = history.ExecutionStart.ToString();
         executionHistory.EndTime = history.ExecutionFinish.ToString();
         executionHistory.Machine = history.ComputerName;
         executionHistory.InstanceId = history.InstanceID.ToString();
         executionHistory.Status = history.Status.ToString();
        //executionHistory.Id = history.JobOID.AsString;
         executionHistory.Id = history.OID.AsString; //passing this as the instance ID.
           
          jobDetails.ExecutionHistoryList.Add(executionHistory);
}
                            

 

Bill Staff (599 posts)
August 16, 2017 10:42 AM
Accepted Answer

That should work for getting the OID. What's the string value you end up using for instanceId when you call your method? What line of code is failing? What exception do you get?

I realized there's another method you can use that saves the overhead of fetching the instance first. You can use this single line (note that JobServices is on the Scheduler object, not on the DataContext):

connection.JobServices.AcknowledgeInstanceStatus(new OID[]{instanceId});


phavanagi (15 posts)
August 16, 2017 11:03 AM
Accepted Answer

It gives me an "invalid OID" and goes to the catch block after the line :

var oid=new OID(instanceId);

I get String as : B474CCC9-EB0B-4552-8550-C5C951BAB441 ->using this as a string.

Also,

connection.JobServices.AcknowledgeInstanceStatus(new OID[] { instanceId }); gives an error as cannot convert string to OID.

Bill Staff (599 posts)
August 16, 2017 12:37 PM
Accepted Answer

That's not a valid OID representation. AsString() should be returning "18:{B474CCC9-EB0B-4552-8550-C5C951BAB441}". Please check what you're getting back from AsString and make sure it's not getting messed up somewhere along the way.

If that looks correct, show me the code you're using to fetch the instances so I can see what's going on.

phavanagi (15 posts)
August 16, 2017 12:50 PM
Accepted Answer
public void acknowledge(string jobId)
   {
    try
    {              
     string connectionDesciptor = Scheduler.BuildConnectionDescriptor(ConfigurationManager.AppSettings["AdTempusServer"], Int32.Parse(ConfigurationManager.AppSettings["AdTempusPort"]), "");
     using (Scheduler connection = Scheduler.Connect(connectionDesciptor, LoginAuthenticationType.Windows, "phavanagi", "Newuser$123"))
      {
       using (DataContext context = connection.NewDataContext())
         {
            var oid = new OID(jobId);
            var instance = (ExecutionHistoryItem)context.GetObject(oid);
            instance.AcknowledgeStatus(0);
}
}
}

Yes, I am getting  "18:{B474CCC9-EB0B-4552-8550-C5C951BAB441}" like this. I render it and send only the OID to the route to get that instance acknowledged, did the same for job id and it was working.

Currently I am not fetching any instance, I am just passing the OID in the route to check if the code is working.

My controller calls the acknowledge function. My route is /api/jobs/acknowledge/B474CCC9-EB0B-4552-8550-C5C951BAB441

Bill Staff (599 posts)
August 16, 2017 01:06 PM
Accepted Answer

The OID is the full value, including the "18:". You cannot pass just the GUID to the OID constructor; it needs the first part (which tells it what kind of object the identifier is for). If you want to pass just the GUID in your route, then you need to use a different constructor for the OID and tell it the class ID. This is what we did in your other example, to convert a job ID to a valid OID for a job. So you need:

var oid=new OID(ClassID.ExecutionHistoryItem, instanceId);

I missed the OID constructor entirely in my alternate example above; the correct version would be:

var oid=new OID(ClassID.ExecutionHistoryItem, instanceId);
connection.JobServices.AcknowledgeInstanceStatus(new OID[] { oid });

or

connection.JobServices.AcknowledgeInstanceStatus(new OID[] { new OID(ClassID.ExecutionHistoryItem, instanceId) });
phavanagi (15 posts)
August 16, 2017 01:30 PM
Accepted Answer
Yeah, Got it :) Thank you!

Replies are disabled for this topic.