The way to run method each X minutes - jenkins

It seems like I just need to implement kind of a listener, if there is no something similar already.
Let's say I have a method which is executed each time build finishes (RunListener event); but that's not enough and I want to run the method each X minutes. I'm stuck!
So, I wonder if there is a way to do it (kind of a listener, event trigger, whatever).
Any info, thoughts are welcomed!

If you want to execute a task regularly in a Jenkins plugin, you can implement the PeriodicWork extension point.
A minimal example that would automatically register with Jenkins, and be executed every three minutes:
#Extension
public class MyPeriodicTask extends PeriodicWork {
#Override
public long getRecurrencePeriod() {
return TimeUnit.MINUTES.toMillis(3);
}
#Override
protected void doRun() throws Exception {
// Do something here, quickly.
// If it will take longer, use AsyncPeriodWork instead
}
}

Related

Order of execution on stream listeners?

Is there a way to enforce the order of execution for a broadcast stream with multiple listeners where order of execution matters?
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError});
The abstract definition doesn't seem to support it. I was looking for perhaps something like a 'priority' parameter to specify the order of operation.
For example, right now I have a UserController that notify its listeners to do something when the user changes. However, some of the listeners need to be prioritised, but they need to be in their own separate class. Example code:
class UserController{
Stream user;
}
class IndependentControllerA {
//...
userController.user.listen((){
// This needs to be carried out first before everything else
}
//...
}
class IndependentControllerB {
userController.user.listen((){
// This needs to be carried out before A
}
}
What I have thought to overcome this is for UserController to instead register a list of its own Future callbacks that can be awaited in order. See example:
class UserController {
List<Future Function()> callbacks;
void changeUser() async {
callbacks.forEach((callback) => await callback());
}
}
class IndependentControllerA {
//...
userController.callbacks.add(() => print('Do first thing'));
//...
}
class IndependentControllerB {
//...
userController.callbacks.add(() => print('Do second thing'));
//...
}
However, I feel that this is not very elegant, if there is a better innate way to do this already with stream. Is there?
The order that listeners are notified in is definitely not something Dart promises. In practice, it's likely to be ordered in some way depending on the order the listeners were added, but it's not a guarantee, and it might change at any time. (Not really, there's definitely badly written code which depends on the ordering and will break if the ordering changes, but that just means there'll have to be a good reason for the change, not that it can't happen).
I'd write my own "prioritizer" if I had such a specific need. Something like what you have started here. Knowing the specific requirements you have might make it much simpler than making a completely general solution.

How to test entity framework execution strategy?

We have an Entity Framework execution strategy coded in our lower environment. How do we test this to show it's actually working? We don't want to release to Prod without something to say we aren't introducing new problems.
The easy way is to use some listener where you can throw an exception and subscribe this listener to the dbContext.
public class CommandListener
{
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
{
throw new TimeoutException("Test exception");
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
public void OnCommandExecuted(object result, bool async)
{
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandError")]
public void OnCommandError(Exception exception, bool async)
{
}
}
Subscribe listener to dbContext f.i. in Startup.cs
var context = provider.GetService<SomeDbContext>();
var listener = context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandListener());
As TimeoutException is transient exception in SqlServerRetryingExecutionStrategy.cs (if you use the default retrying strategy) you will get TimeoutException as many as your MaxRetryingCount of strategy setting has. Finally, you have to get RetryLimitExceededException as a result of the request.
You have to see TimeoutException in your app logs. Also it is good idea to turn on transaction logs "Microsoft.EntityFrameworkCore.Database.Transaction": "Debug"
What I did to manage to throw the transient exception and debug strategy (testing and playing around purpose only)
I added ExectuionStrategyBase.cs and
TestServerRetryingExecutionStrategy.cs. The first one is clone of
ExectuionStrategy.cs and second one is clone of
SqlServerRetryingExecutionStrategy.cs
In Startup.cs I set retrying strategy
strategy services.AddDbContext<SomeDbContext>(options =>
{options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sqlOption =>
{
sqlOption.ExecutionStrategy(dependencies =>
{
return new TestSqlRetryingStrategy(
dependencies,
settings.SqlMaxRetryCount,
settings.SqlMaxRetryDelay,
null);
});
});
In OnCommandExecuting of CommandListener.sc I just checked some static bool variable to throw or not TimeoutException and in ExectuionStrategyBase.cs I swithced that variable.
Thus, I managed to throw transient Exception on the first execution of the query and successful execution on the second short. Now I think about some long running transaction and kill session of this transaction in SSCM during execution of it.
Also, I found out that if there is a query like
var users = context.Users.AsNoTracking().ToArrayAsync() execution strategy is not implemented and I am stuck on it. I have been struggling with that a couple of days but still can figure out nothing. If remove AsNoTracking or replace ToArrayAsync() by something like FirstAsync() all foes well.

Detach event in Vaadin web app not getting called

My question stems from an issue almost identical to the one here (which did not end up getting a satisfactory answer):
https://vaadin.com/forum/thread/13932610
Like this person, I expected that upon closing the browser that my app was open in, a detach event would proc; however, this did not happen. I've tried adding a detach listener, overriding the detach method, and doing both at the same time, but none of them were successful. As for how I know the detach event was not called, my detach event is a simple print statement - that does not show up in the output.
Note that like in the aforementioned thread, I've already set the heartbeat interval (2 seconds in my case) and set closeIdelSessions to be true. So, I thought I would just have to wait six seconds, but that's certainly not been the case.
When I try this (find the essential parts of the code below), the detach() is eventually being called. I run this with Jetty, and I did not touch its default. It tooks some ~45 minutes after closing the Browser, when I saw "Detach called" logged on console. So yes, the time is lengthy. The reason is that the last UI is cleaned up only after HttpSession is expired (which depends on application container etc. settings). If you want to do forced clean up quicker, you need to use https://vaadin.com/directory/component/cleanupservlet-add-on
#Push
#SuppressWarnings("serial")
public class DemoUI extends UI {
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = DemoUI.class, heartbeatInterval=5, closeIdleSessions=true)
public static class Servlet extends VaadinServlet {
}
#Override
public void detach() {
System.out.println("Detach called");
}
#Override
protected void init(VaadinRequest vaadinRequest) {
...
}

Amazon SWF queries

Over the last couple of years, I have done a fair amount of work on Amazon SWF, but the following points are still unclear to me and I am not able to find any straight forward answers on any forums yet.
These are pretty basic requirements I suppose, sure others might have come across too. Would be great if someone can clarify these.
Is there a simple way to return a workflow execution result (maybe just something as simple as boolean) back to workflow starter?
Is there a way to catch Activity timeout exception, so that we can do run customised actions in such scenarios?
Why doesn't WorkflowExecutionHistory contains Activities, why just Events?
Why there is no simple way of restarting a workflow from the point it failed?
I am considering to use SWF for more business processes at my workplace, but these limitations/doubts are holding me back!
FINAL WORKING SOLUTION
public class ReturnResultActivityImpl implements ReturnResultActivity {
SettableFuture future;
public ReturnResultActivityImpl() {
}
public ReturnResultActivityImpl(SettableFuture future) {
this.future = future;
}
public void returnResult(WorkflowResult workflowResult) {
System.out.print("Marking future as Completed");
future.set(workflowResult);
}
}
public class WorkflowResult {
public WorkflowResult(boolean s, String n) {
this.success = s;
this.note = n;
}
private boolean success;
private String note;
}
public class WorkflowStarter {
#Autowired
ReturnResultActivityClient returnResultActivityClient;
#Autowired
DummyWorkflowClientExternalFactory dummyWorkflowClientExternalFactory;
#Autowired
AmazonSimpleWorkflowClient swfClient;
String domain = "test-domain;
boolean isRegister = true;
int days = 7;
int terminationTimeoutSeconds = 5000;
int threadPollCount = 2;
int taskExecutorThreadCount = 4;
public String testWorkflow() throws Exception {
SettableFuture<WorkflowResult> workflowResultFuture = SettableFuture.create();
String taskListName = "testTaskList-" + RandomStringUtils.randomAlphabetic(8);
ReturnResultActivity activity = new ReturnResultActivityImpl(workflowResultFuture);
SpringActivityWorker activityWorker = buildReturnResultActivityWorker(taskListName, Arrays.asList(activity));
DummyWorkflowClientExternalFactory factory = new DummyWorkflowClientExternalFactoryImpl(swfClient, domain);
factory.getClient().doSomething(taskListName)
WorkflowResult result = workflowResultSettableFuture.get(20, TimeUnit.SECONDS);
return "Call result note - " + result.getNote();
}
public SpringActivityWorker buildReturnResultActivityWorker(String taskListName, List activityImplementations)
throws Exception {
return setupActivityWorker(swfClient, domain, taskListName, isRegister, days, activityImplementations,
terminationTimeoutSeconds, threadPollCount, taskExecutorThreadCount);
}
}
public class Workflow {
#Autowired
private DummyActivityClient dummyActivityClient;
#Autowired
private ReturnResultActivityClient returnResultActivityClient;
#Override
public void doSomething(final String resultActivityTaskListName) {
Promise<Void> activityPromise = dummyActivityClient.dummyActivity();
returnResult(resultActivityTaskListName, activityPromise);
}
#Asynchronous
private void returnResult(final String taskListname, Promise waitFor) {
ActivitySchedulingOptions schedulingOptions = new ActivitySchedulingOptions();
schedulingOptions.setTaskList(taskListname);
WorkflowResult result = new WorkflowResult(true,"All successful");
returnResultActivityClient.returnResult(result, schedulingOptions);
}
}
The standard pattern is to host a special activity in the workflow starter process that is used to deliver the result. Use a process specific task list to make sure that it is routed to a correct instance of the starter. Here are the steps to implement it:
Define an activity to receive the result. For example "returnResultActivity". Make this activity implementation to complete the Future passed to its constructor upon execution.
When the workflow is started it receives "resultActivityTaskList" as an input argument. At the end the workflow calls this activity with a workflow result. The activity is scheduled on the passed task list.
The workflow starter creates an ActivityWorker and an instance of a Future. Then it creates an instance of "returnResultActivity" with that future as a constructor parameter.
Then it registers the activity instance with the activity worker and configures it to poll on a randomly generated task list name. Then it calls "start workflow execution" passing the generated task list name as an input argument.
Then it wait on the Future to complete. The future.get() is going to return the workflow result.
Yes, if you are using the AWS Flow Framework a timeout exception is thrown when activity is timed out. If you are not using the Flow framework than you are making your life 100 times harder. BTW the workflow timeout is thrown into a parent workflow as a timeout exception as well. It is not possible to catch a workflow timeout exception from within the timing out instance itself. In this case it is recommended to not rely on workflow timeout, but just create a timer that would fire and notify workflow logic that some business event has timed out.
Because a single activity execution has multiple events associated to it. It should be pretty easy to write code that converts history to whatever representation of activities you like. Such code would just match the events that relate to each activities. Each event always has a reference to the related events, so it is easy to roll them up into higher level representation.
Unfortunately there is no easy answer to this one. Ideally SWF would support restarting workflow by copying its history up to the failure point. But it is not supported. I personally believe that workflow should be written in a way that it never fails but always deals with failures without failing. Obviously it doesn't work in case of failures due to unexpected conditions. In this case writing workflow in a way that it can be restarted from the beginning is the simplest approach.

Groovy method interception

In my Grails app I've installed the Quartz plugin. I want to intercept calls to every Quartz job class' execute method in order to do something before the execute method is invoked (similar to AOP before advice).
Currently, I'm trying to do this interception from the doWithDynamicMethods closure of another plugin as shown below:
def doWithDynamicMethods = { ctx ->
// get all the job classes
application.getArtefacts("Job").each { klass ->
MetaClass jobMetaClass = klass.clazz.metaClass
// intercept the methods of the job classes
jobMetaClass.invokeMethod = { String name, Object args ->
// do something before invoking the called method
if (name == "execute") {
println "this should happen before execute()"
}
// now call the method that was originally invoked
def validMethod = jobMetaClass.getMetaMethod(name, args)
if (validMethod != null) {
validMethod.invoke(delegate, args)
} else {
jobMetaClass.invokeMissingMethod(delegate, name, args)
}
}
}
}
So, given a job such as
class TestJob {
static triggers = {
simple repeatInterval: 5000l // execute job once in 5 seconds
}
def execute() {
"execute called"
}
}
It should print:
this should happen before execute()
execute called
But my attempt at method interception seems to have no effect and instead it just prints:
execute called
Perhaps the cause of the problem is this Groovy bug? Even though the Job classes don't explicitly implement the org.quartz.Job interface, I suspect that implicitly (due to some Groovy voodoo), they are instances of this interface.
If indeed this bug is the cause of my problem, is there another way that I can do "before method interception"?
Because all the job classes are Spring beans you can solve this problem using Spring AOP. Define an aspect such as the following (adjust the pointcut definition so that it matches only your job classes, I've assumed they are all in a package named org.example.job and have a class name that ends with Job).
#Aspect
class JobExecutionAspect {
#Pointcut("execution(public * org.example.job.*Job.execute(..))")
public void executeMethods() {}
#Around("executeMethods()")
def interceptJobExecuteMethod(ProceedingJoinPoint jp) {
// do your stuff that should happen before execute() here, if you need access
// to the job object call jp.getTarget()
// now call the job's execute() method
jp.proceed()
}
}
You'll need to register this aspect as a Spring bean (it doesn't matter what name you give the bean).
You can have your customized JobListener registered in the application to handle logics before execute() is triggered. You can use something like:-
public class MyJobListener implements JobListener {
public void jobToBeExecuted(JobExecutionContext context) {
println "Before calling Execute"
}
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {}
public void jobExecutionVetoed(JobExecutionContext context) {}
}
Register the customized Job Listener to Quartz Scheduler in Bootstrap:-
Scheduler scheduler = ctx.getBean("quartzScheduler") //ctx being application context
scheduler.getListenerManager().addJobListener(myJobListener, allJobs())
resources.groovy:-
beans = {
myJobListener(MyJobListener)
}
One benefit I see here using this approach is that we don't need the second plugin used for method interception any more.
Second, we can register the listener to listen all jobs, specific jobs, and jobs in a group. Refer Customize Quartz JobListener and API for JobListener, TriggerListener, ScheduleListener for more insight.
Obviously, AOP is another approach if we do want want to use Quartz API.
You are not getting the job classes like that. If you refer to the Quartz plugin, you can get them by calling jobClasses:
application.jobClasses.each {GrailsJobClass tc -> ... }
see https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovy
If you actually look, you can see that they are almost doing what you are trying to acheive without the need to use aop or anything else.
For method interception implement invokeMethod on the metaclass. In my case the class was not of third party so I can modify the implementation.
Follow this blog for more information.

Resources