I'm separating my business methods and scheduled methods.
What are possible merits of following code
#Singleton
#Startup
public class MySchedule {
#Schedule(...)
public void doSome() {
}
}
over following code?
#Stateless
public class MySchedule {
#Schedule(...)
public void doSome() {
}
}
I read definitions of #Singleton and #Startup. But I see the method of the class annotated solely with #Stateless also works as scheduled.
Is there any differences or preferences?
That depends on the container implementation (and EJB spec).
A #Stateless will act as is and you should not have a state in it!
The method is invoked for each schedule, Wildfly will prevent from concurrent call, the schedule will be skipped with a WARN message if the timer is still running (i.e. 1minute schedule and the execution take more)
A #Singleton might keep a state (i.e. start initialization) and during the scheduled events.
By spec you can't invoke this instance concurrent until you add Lock.READ, this mean as long as the scheduler run you are not able to invoke any other method.
For concurrent schedule of the same it is not possible anyway (see above)
That mean also you can not run two #Schedule methods at the same time as well.
I'm not sure whether other containers allow concurrent execution for timers.
If you have a single schedule (and nothing else in the implementation) it should not make a difference.
And the #Startup will not make much sense then also ;)
Related
I was using Flink CEP module and wondering if I pass a function to where clause, which would be returning Boolean, whether it will work in distributed manner or not.
Example-:
val pattern= Pattern.start("begin").where(v=>booleanReturningFunction(v))
Will the above code work in distributed manner when submitted as flink job for CEP with simple condition.
Yuval already gave the correct answer in the comments but I'd like to expand on it:
Yes, any function that you provide can be run in a distributed fashion. First of all, as Yuval pointed out, all your code gets distributed on the compute cluster on job submission.
The missing piece is that also your job itself gets distributed. If you check the API, you see it in the interfaces:
public Pattern<T, F> where(IterativeCondition<F> condition) { ...
Pattern expects some condition. If you look at its definition, you can see the following
public abstract class IterativeCondition<T> implements Function, Serializable { ... }
So the thing that you pass to where has to be Serializable. Your client can serialize your whole job including all function definitions and send it to the JobManager, which distributes it to the different TaskManagers. Because every piece of the infrastructure also has your job jar, it can deserialize the job including your function. Deserialization also means it creates copies of the function, which is necessary for distributed execution.
Assuming the following pipeline:
input.filter(new RichFilterFunction<MyPojo>() {
#Override
public boolean filter(MyPojo value) throws Exception {
return false;
}
});
How many instances of the above rich function will be created?
Per task with no exceptions
Per task, however all parallel tasks on a particular node share one instance, since they are part of one JVM instance
There will always be as many instances as the parallelism indicates. There are two reasons related to state for that:
If your function maintains a state, especially in a keyed context, a shared instance would cause unintended side effects.
In the early days, users liked to maintain their own state (e.g., remembering previous value). Even though, it's heavily discouraged, it would still be bad if Flink could not support that.
In the helper I have methods that each call an #AuraEnabled method in the component controller.
Some of these calls are only during the 'init' event.
From a performance point of view I should make only one call during 'init'.
What is an elegant way of achieving this?
The methods called during 'init' return a list of strings, a decimal, and respectively a string.
Define a custom Apex class in your controller that encapsulates all of the information you wish to source in a single call from your init event:
public class InitializationWrapper {
#AuraEnabled
public List<String> myStringList {get; set;}
#AuraEnabled
public Decimal myDecimal {get; set;}
#AuraEnabled
public String myString {get; set;}
}
The, return an instance of this wrapper class from your server-side Apex call to your init handler. You only need to make a single round-trip.
I'd swear you don't have to do anything, no fancy coding, SF would do it for you as part of Aura framework...
Used to work for me like a charm a while ago (in fact even other way around, it was for sure 1 Apex call = all methods I had were using same governor limits, I had to rework some queries)
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_actions_call.htm
$A.enqueueAction(action) adds the server-side controller action to the
queue of actions to be executed. All actions that are enqueued will
run at the end of the event loop. Rather than sending a separate
request for each individual action, the framework processes the event
chain and batches the actions in the queue into one request. (...) The
framework batches the actions in the queue into one server request.
The request payload includes all of the actions and their data
serialized into JSON. The request payload limit is 4 MB.
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_actions_queue.htm
The framework queues up actions before sending them to the server.
This mechanism is largely transparent to you when you’re writing code
but it enables the framework to minimize network traffic by batching
multiple actions into one request (XHR). The batching of actions is
also known as boxcar’ing, similar to a train that couples boxcars
together.
The framework uses a stack to keep track of the actions to send to the
server. When the browser finishes processing events and JavaScript on
the client, the enqueued actions on the stack are sent to the server
in a batch.
If this doesn't work as described for you (can you post some code?) and request size is < 4 MB... Maybe they broke something and you've found a platform bug. You're sure you see separate entries in Debug Log? Or in network traffic monitoring in browser?
Maybe you need to play with background actions. I mean this is supposed to work without extra crutches in Apex to bundle multiple calls into one, create complex response wrapper class and every callback unpicks only data it cares about, that's lots of unneccessary code :/
Let's say I have following time component:
from("timer://foo?period=1000").setBody(constant("select * from customer")).to("jdbc:testdb").to("beanRef:processResult");
How does timer component work here? Does it reads from database in every 1 sec or waits for bean to finish the processing?
If bean is still processing the earlier result and timer will keep polling the database then it will create a bottleneck. Is there any way to avoid it?
Okay, Update: looking at the source code, the timer component relies on the java TimerTask implementation. And your question is already answered here: Is Java's Timer task guarenteed not to run concurrently?
Short answer: one single thread executes the trigger and the routes connected to it, so there will be no concurrent execution.
That said, you might want to controll the execution a bit. It is recommended with Timer Tasks (and hence Camel timers) to have a margin between the period in the timer and the max task execution time.
You can use a SEDA component (with concurrentConsumers=[num threads]) in between to fine grain controll the execution with a work queue. The timer will finish it's task right away while the real route can continue to process.
from("timer://foo?period=1000")
.to("seda:startRoute");
from("seda:startRoute")
.setBody(constant("select * from customer"))
.to("jdbc:testdb").to("beanRef:processResult");
Each event will stack up non the less, so over time, you might want tune the route so that the period > avg route exec time.
You could add a shared boolean variable either in a singleton bean or in a static class:
public static synchronized boolean isRunning(){
return running;
}
public static synchronized void setRunning(boolean isRunning){
running = isRunning;
}
The variable should telling weather the route is running or not and filter timer events that occurs while the variable is true. Just hook up a few processors/bean-calls to handle this.
I considered putting this as an additional question in this thread:
Unit testing with MVVM Light & DispatcherHelper
but as I delved into it, I think it's a little different.
I have one project containing view models/views, a separate project containing models, and a third separate unit test project (MSTest) containing tests for the models. I'm using MVVM Light's DispatcherHelper to help me do work in a background task, but to get errors from that task back to the UI.
The view model/view project has the App.xaml.cs file, which contains the OnStartup event handler, in which I've put the DispatcherHelper.Initialize() call. One of the VMs invokes a call to one of the model's long-running methods on another thread using delegate.BeginInvoke():
FileProcessDelegate processor = GenerateAddressingFile;
processor.BeginInvoke(FileGenerationComplete, null);
In this long-running method, it calls a utility method to send errors back to the UI. These are in the form of mvvm-light messages that are sent using the DispatcherHelper.CheckBeginInvokeOnUI()
internal static void ReportErrorToUi(IFileError error)
{
DispatcherHelper.CheckBeginInvokeOnUI(
() => Messenger.Default.Send(new GenericMessage<IFileError>(error), MessageTokens.ReportFileError));
}
This all seems to work fine in the app.
In one of the unit test classes for the model, I attempt to check that the long-running method correctly sends messages when errors occur. In that test class, I have a call to DispatcherHelper.Initialize() in the MSTest class initialization method.
#region Additional test attributes
//
//You can use the following additional attributes as you write your tests:
//
//Use ClassInitialize to run code before running the first test in the class
[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
DispatcherHelper.Initialize();
}
The test registers for the message that should be sent, then calls the model's method directly, without invoking it on a separate thread. As I understand it, because the call to send the message is wrapped by DispatcherHelper.CheckBeginInvokeOnUI() in the model, it should do the right thing regardless of whether it is occurring on a background thread or on the UI thread.
In the first test of this class that checks the method, everything works fine. The test receives the error messages being sent back and passes with flying colors.
When subsequent tests in the same class run, the messages are never received by the test. When I've stepped through it on these subsequent tests, I notice that when I get to the DispatcherHelper.CheckBeginInvokeOnUI() method, the DispatcherHelper.UIDispatcher.Thread instance says it's dead.
Any thoughts?
I'm not sure if this solution is something that can be included in Mvvm Light, or if it violates some base premises of the framework, but here's what I did to get this to work:
I made a custom local version of the DispatcherHelper class that has one minor difference from what's in Mvvm Light, namely the logic in the Initialize() method:
public static void Initialize()
{
if (UIDispatcher != null &&
UIDispatcher.Thread.IsAlive)
{
return;
}
UIDispatcher = Dispatcher.CurrentDispatcher;
}
Here, the change is the addition of:
&& UIDispatcher.Thread.IsAlive
to the condition. This allows me to call DispatcherHelper.Initialize() in the MyTestInitialize() method of my unit test class. That way, if the previous thread that the UIDispatcher was associated with has died, the DispatcherHelper gets the new Dispatcher/Thread that this current test method will be run on.
Apparently, in the VSTS Testing framework, there is not a "central" thread that acts like the UI thread in an application. The MyClassInitialize() method was executed on one thread, and then the tests were run on a completely different thread. The Mvvm Light definition wouldn't let me hook the DispatcherHelper up to the new test thread by calling DispatcherHelper.Initialize() again because the UIDispatcher wasn't null, it's thread was just dead.
Testing async code is tricky. Typically, if it works once, and then not anymore, it sounds like you are not synchronizing your threads correctly. In your test method (main thread), are you waiting for the background thread to execute?
Jonas Follesoe wrote a few good articles about async unit testing in Silverlight, for example http://jonas.follesoe.no/2007/09/18/unit-testing-event-based-asynchronous-code/. This is typically how I unit test my async code too.
Hope this helps,
Laurent