hi @ all,

limiting it to the scheduler-module is possible - but if it is the only
use-case, it wouldn't be needed, because it's easier to use
Scheduler#unwrap to register your own TriggerListener via
#getListenerManager. in the end such use-cases are the reason for
Scheduler#unwrap.

regards,
gerhard



Am Mo., 4. Feb. 2019 um 17:26 Uhr schrieb Mark Struberg
<[email protected]>:

> doesn't sound wrong - actually sounds really fine ;)
>
> Do you probably want to provide a ticket and patch?
>
> LieGrue,
> strub
>
> > Am 04.02.2019 um 14:19 schrieb Juri Berlanda <[email protected]
> >:
> >
> > Hi,
> >
> > I still think it would be nice to just have a simple mechanism telling
> "Just don't start here".
> >
> > I'm sceptic on a.) and b.) because they would introduce a database
> binding to DeltaSpike, which I think may make it hard to use in some stacks
> (think projects running on NoSQL databases). In addition, I think something
> similar as you proposed in a.) can already be achieved by running Quartz in
> ClusteredMode, though I never tried that.
> >
> > What I would propose is some pluggable Bean (via Alternative,
> Specializes or stuff like that) with 2 functions:
> >
> > boolean isSchedulerEnabled();
> >
> > boolean shouldJobBeStarted(Class<T>);
> >
> > The default implementation would return true on both. Any Alternative
> could then return false on isSchedulerEnabled() to fully disable it
> (lowering overall overhead in a scenario as mine), or do something smart in
> shouldJobBeStarted() to determine at Runtime whether a specific Job should
> be ran on the current node (should accomodate for your usecase).
> >
> > What do you think?
> >
> > Cheers,
> >
> > Juri
> >
> > On 1/30/19 9:13 AM, Mark Struberg wrote:
> >> Hi folks!
> >>
> >> Yes, that solution works.
> >>
> >> I had the same problem (multiple nodes, code should only run once).
> >> Pinning to one cluster node is a possible solution, but if that one
> node is down then the processing stops.
> >> I went for another solution. I wrote some Interceptor which basically
> guards against a central DB.
> >>
> >> There are 2 different strategies:
> >> a.) Keep an pesimistic lock on a row in a DB. One row per Class or
> locking key. (DB must support row locking).
> >>  Pro: easy to implement. Most work is done by the database
> >>  Con: If the whole thread gets stuck then you're in back luck. One is
> also bound to the maximum transaction timeout.
> >>   So if you want to have a task running for one hour (doing e.g.
> multiple transaction batches) you cannot use this strategy.
> >>
> >> b.) Have a 'watchdog' table which remembers the node and whether
> active. 2 Minutes not updated means that the task blew up and another node
> might take up.
> >>  Pro: sufficiently easy to implement. A background thread which is a
> watchdog and uipdates the 'lastActive' timestamp in the DB in the
> background.
> >>  Con: It takes a while for another node to pick up the work. Minimum 2
> minutes. We also need a clear 'nodeId'. That might be the IP, but if
> multiple JVMs run on the same box then you need some custom identifier. The
> JVM id would be a candidate as it is unique. Otoh a restart would mean 2
> minutes pause.
> >>
> >> c.) no database at all but network based locking. Might be easier or
> harder to setup depending on your infrastructure and security measures.
> >>
> >> Should we implement any of these in DeltaSpike?
> >> Which one makes more sense?
> >> (I personally went for option b for my use cases)
> >>
> >> LieGrue,
> >> strub
> >>
> >>
> >>> Am 28.01.2019 um 13:28 schrieb Juri Berlanda <
> [email protected]>:
> >>>
> >>> Hi,
> >>>
> >>> just for completeness sake: I was able to achieve what I wanted using
> a custom config source. I presume this is not how it is supposed to be, but
> it works:
> >>>
> >>> public class SchedulerConfigSource implements ConfigSource {
> >>>     private static final String CLASS_DEACTIVATOR_KEY =
> "org.apache.deltaspike.core.spi.activation.ClassDeactivator";
> >>>     private static final String CLASS_DEACTIVATOR_VALUE =
> "org.apache.deltaspike.core.impl.activation.DefaultClassDeactivator";
> >>>     private static final String SCHEDULER_DISABLED_KEY =
> "deactivate.org.apache.deltaspike.scheduler.impl.SchedulerExtension";
> >>>
> >>>     private final int ordinal;
> >>>
> >>>     SchedulerConfigSource(int ordinal) {
> >>>         this.ordinal = ordinal;
> >>>     }
> >>>
> >>>     @Override
> >>>     public int getOrdinal() {
> >>>         return ordinal;
> >>>     }
> >>>
> >>>     @Override
> >>>     public Map<String, String> getProperties() {
> >>>         return Stream.of(CLASS_DEACTIVATOR_KEY, SCHEDULER_DISABLED_KEY)
> >>>                 .collect(Collectors.toMap(Function.identity(),
> this::getPropertyValue));
> >>>     }
> >>>
> >>>     @Override
> >>>     public String getPropertyValue(String key) {
> >>>         if (CLASS_DEACTIVATOR_KEY.equals(key))
> >>>             return CLASS_DEACTIVATOR_VALUE;
> >>>         if (SCHEDULER_DISABLED_KEY.equals(key))
> >>>             return Boolean.toString(!isSchedulerNode());
> >>>         return null;
> >>>     }
> >>>
> >>>     private boolean isSchedulerNode() {
> >>>         // Evaluate the condition here
> >>>     }
> >>>
> >>>     @Override
> >>>     public String getConfigName() {
> >>>         return "SchedulerConfigSource";
> >>>     }
> >>>
> >>>     @Override
> >>>     public boolean isScannable() {
> >>>         return false;
> >>>     }
> >>> }
> >>>
> >>> Thought I may as well add it if somebody else. And don't forget to
> register the ConfigSource.
> >>>
> >>> I presume there is a better way to achieve this. If you know of one,
> please let me know.
> >>>
> >>> Cheers,
> >>>
> >>> Juri
> >>>
> >>> On 1/25/19 3:56 PM, Juri Berlanda wrote:
> >>>> I was able to achieve similar with Deltaspike's own Deactivable. It
> does work, i.e. I can set:
> >>>>
> >>>>
> org.apache.deltaspike.core.spi.activation.ClassDeactivator=org.apache.deltaspike.core.impl.activation.DefaultClassDeactivator
> >>>>
> deactivate.org.apache.deltaspike.scheduler.impl.SchedulerExtension=true
> >>>>
> >>>> in my configs, and Scheduler stays off. But - as mentioned - I need
> this to be evaluated on system startup, not at Config level. So I tried
> implementing my own SchedulerExtension like:
> >>>>
> >>>> public class MySchedulerExtension extends SchedulerExtension {
> >>>>     @Override
> >>>>     protected void init(@Observes BeforeBeanDiscovery
> beforeBeanDiscovery) {
> >>>>         if (isSchedulerNode())
> >>>>             super.init(beforeBeanDiscovery);
> >>>>     }
> >>>> }
> >>>>
> >>>> I can register it via SPI and from the logs I see it is indeed
> initialized, while SchedulerExtension is not. Victory, right? Not quite...
> >>>>
> >>>> I am testing this with OpenWebbeans 2.0.6., and I face the problem,
> that CDI now complains about ambiguous Bean for SchedulerExtension in
> SchedulerProducer (which I can see where that comes from), but I am just
> not able to exclude SchedulerProducer - I wouldn't even need it. I tried
> various combinations of @Specialize, @Alternative and <scan><exclude
> .../></scan>, but none of them seem to work. I guess the reason for it is
> the CDI 1.0 beans.xml in scheduler-impl? Can anybody confirm? Would it be
> possible to move higher - 1.1 at least for getting support for
> <scan><exclude .../></scan>?
> >>>>
> >>>> This leads me to the assumption, that scheduler-impl's
> SchedulerExtension is just not extensible at the moment. Or did anybody
> succeed in such an endeavor?
> >>>>
> >>>> Since I do not want to patch the implementation, my next guess is to
> implement a custom ConfigSource, which evaluates isSchedulerNode() and sets
> deactivate.org.apache.deltaspike.scheduler.impl.SchedulerExtension
> accordingly. Does that make sense?
> >>>>
> >>>> Kind regards,
> >>>>
> >>>> Juri
> >>>>
> >>>> On 1/24/19 9:04 PM, Alex Roytman wrote:
> >>>>> in my case i need to be able to turn it on/off on demand and I only
> have
> >>>>> couple of daily tasks so for me it was good enough
> >>>>> If if you just need to do it on startup by node type you could bind
> it to a
> >>>>> property
> >>>>> @Scheduled(cronExpression = "{reindex.schedule}")
> >>>>> public class ReindexTask implements org.quartz.Job {
> >>>>> ...
> >>>>> and that property could probably be a cron expression which never
> fire on
> >>>>> all of your nodes but the scheduler
> >>>>> not nice but the whole thing is rather static - admittedly i did not
> dig
> >>>>> very deep
> >>>>>
> >>>>>
> >>>>> On Thu, Jan 24, 2019 at 2:44 PM Juri Berlanda <
> [email protected]>
> >>>>> wrote:
> >>>>>
> >>>>>> Thanks for the quick reply. I thought about that, but I don't like
> this
> >>>>>> solution, since it involves to much boilerplate for my taste. In
> >>>>>> addition, I find it cumbersome having to add these 2 lines in every
> >>>>>> single task. I also thought about having an abstract base class for
> this
> >>>>>> purpose, but I'm not happy with the solution...
> >>>>>>
> >>>>>> In short: I hoped for a cleaner solution.
> >>>>>>
> >>>>>> On 1/24/19 7:03 PM, Alex Roytman wrote:
> >>>>>>> Let the scheduler run and execute your task  but inside of the task
> >>>>>> itself
> >>>>>>> check if you want to execute your logic or short circuit it to
> noop.
> >>>>>> Since
> >>>>>>> you do not run it often should not be an overhead and it will let
> you
> >>>>>> fail
> >>>>>>> over for any mode to execute it as long as you have a mechanism to
> lock
> >>>>>> on
> >>>>>>> something and record execution result to avoid simultaneous
> execution or
> >>>>>>> double exexution
> >>>>>>>
> >>>>>>> On Thu, Jan 24, 2019, 12:37 PM Juri Berlanda <
> [email protected]
> >>>>>>> wrote:
> >>>>>>>
> >>>>>>>> Hi,
> >>>>>>>>
> >>>>>>>> I am currently trying to implement scheduled jobs using
> DeltaSpike's
> >>>>>>>> Scheduler module, and I really like how little boilerplate I need
> for
> >>>>>>>> getting it up and running.
> >>>>>>>>
> >>>>>>>> Our application runs on multiple nodes, but the tasks are very
> >>>>>>>> inexpensive, run only once a day, and I don't need failover - if
> they
> >>>>>>>> fail once, and succeed the day after its totally fine. Therefore
> I'd
> >>>>>>>> like to avoid setting up Quartz in clustered mode. But I still
> want the
> >>>>>>>> Jobs to only run once. So my idea was to restrict the execution
> of the
> >>>>>>>> jobs to a single scheduler node.
> >>>>>>>>
> >>>>>>>> So my question is: Is it possible to somehow hook into the
> Scheduler
> >>>>>>>> module to say something like:
> >>>>>>>>
> >>>>>>>> if (isSchedulerNode())
> >>>>>>>>      startScheduler();
> >>>>>>>> else
> >>>>>>>>      doNothing();
> >>>>>>>>
> >>>>>>>> It would be perfect if said isSchedulerNode() could be evaluated
> on
> >>>>>>>> system startup (e.g. acquire a distributed lock) and would not
> rely on
> >>>>>>>> static values (e.g. config files, environment variables, etc.).
> >>>>>>>>
> >>>>>>>> I can see how this is a bad idea in general (no load-balancing, no
> >>>>>>>> failover) and I do have some ideas on how I would implement that.
> But
> >>>>>>>> for these jobs I just don't care about any of this, so I'd like
> to avoid
> >>>>>>>> having to set up a whole lot of infrastructure around my
> application
> >>>>>>>> just to see this working.
> >>>>>>>>
> >>>>>>>> Is there a possibility to achieve this without patching
> >>>>>>>> deltaspike-scheduler-module-impl?
> >>>>>>>>
> >>>>>>>> Kind regards,
> >>>>>>>>
> >>>>>>>> Juri
> >>>>>>>>
> >>>>>>>>
>
>

Reply via email to