How to cancel a recurring job in firebase job dispatcher - firebase-job-dispatcher

I have created a recurring job, I want to cancel the recurring job when some conditions met.
final Job.Builder builder = dispatcher.newJobBuilder()
.setTag("myJob")
.setService(myJobService.class)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(30, 60));
How can i cancel a job in firebase ?

The readme on GitHub says:
Driver is an interface that represents a component that can schedule,
cancel, and execute Jobs. The only bundled Driver is the
GooglePlayDriver, which relies on the scheduler built-in to Google
Play services.
So cancelling is part of the driver you are using. Inspecting the code of the driver interface there are two methods to cancel a job:
/**
* Cancels the job with the provided tag and class.
*
* #return one of the CANCEL_RESULT_ constants.
*/
#CancelResult
int cancel(#NonNull String tag);
/**
* Cancels all jobs registered with this Driver.
*
* #return one of the CANCEL_RESULT_ constants.
*/
#CancelResult
int cancelAll();
So in your case you have to call:
dispatcher.cancel("myJob");
or
dispatcher.cancelAll();
The dispatcher will call the corresponding method of the driver for you. If you want you can also call the methods directly on your driver myDriver.cancelAll() like it is done in the sample app which comes with the GitHub project.
The chosen method will return one of the following constants:
public static final int CANCEL_RESULT_SUCCESS = 0;
public static final int CANCEL_RESULT_UNKNOWN_ERROR = 1;
public static final int CANCEL_RESULT_NO_DRIVER_AVAILABLE = 2;

Related

Laravel Nova: Queuable actions create single job for multiple resources

I have a simple Action in Laravel Nova which updates stock inventory via an API call. I want to be able to queue this as individual jobs for each product that requires an update to stagger the API calls.
When I add my action to a resource and run it via the index page by selecting multiple products and running the action, only a single job is created in my jobs table.
So when the queue is processed, rather than queuing each product for an individual update, a single job is run which loops all selected products and makes multiple API requests in quick succession, which is not my desired result.
Is there a way for the action to create a job for each resource that the action is run against?
Action Class
class UpdateInventory extends Action implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
$this->connection = config('queue.default');
$this->queue = 'inventory_update';
}
/**
* Perform the action on the given models.
*/
public function handle(ActionFields $fields, Collection $products)
{
foreach ($products as $product) {
try {
$inventoryService = resolve(InventoryService::class);
$inventoryService->updateProductInventory($product); // <- API calls within
$this->markAsFinished($product);
} catch (\Exception $e) {
$this->markAsFailed($product, $e);
}
}
return Action::message("Inventory update started");
}
}
class UpdateInventory extends Action implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
/**
* The number of models that should be included in each chunk.
*
* #var int
*/
public static $chunkCount = 1;
}
You may instruct Nova to your queue actions as a batch. That requires migration so you create batches table with following command php artisan queue:batches-table and migrate your database. This table contains total_jobs, pending_jobs, failed_jobs, failed_job_ids fields so you can keep track each job. If each job has one resource, it should resolve your issue.
More information:
Laravel Nova Actions - Job Batching
Laravel Queues - Job Batching

How can we persist states and transitions in stateless4j based State Machine?

I am working on implementing a state machine for a workflow management system based on the Stateless4j API. However, I am not able to find an effective way to persist the states and transitions in Stateless4j.
As part of our usecases, we have the requirement to keep States alive for more than 3 - 4 days until the user returns to the workflow. And we will have more than one workflow running concurrently.
Can you please share your insights on the best practices to persist states in Stateless4j based State Machine implementation?
It looks like what you need to do is construct your StateMachine with a custom accessor and mutator, something like this:
public class PersistentMutator<S> implements Action1<S> {
Foo foo = null;
#Inject
FooRepository fooRepository;
public PersistentMutator(Foo foo) {
this.foo = foo;
}
#Override
public void doIt(S s) {
foo.setState(s);
fooRepository.save(foo)
}
}
Then you want to call the constructor with your accessors and mutators:
/**
* Construct a state machine with external state storage.
*
* #param initialState The initial state
* #param stateAccessor State accessor
* #param stateMutator State mutator
*/
public StateMachine(S initialState, Func<S> stateAccessor, Action1<S> stateMutator, StateMachineConfig<S, T> config) {
this.config = config;
this.stateAccessor = stateAccessor;
this.stateMutator = stateMutator;
stateMutator.doIt(initialState);
}
Alternatively, you may want to look at StatefulJ. It has built in support for atomically updating state in both JPA and Mongo out of the box. This may save you some time.
Disclaimer: I'm the author of StatefulJ

JPA: Automatically delete data after timeinterval

I've the following scenario:
Data will be created by the sender on the server.
If the receiver won't request the data within (for example) three days, the data should be deleted otherwise the receiver gets the data and after getting the data, the data will be deleted.
In other words:
The data should only exist for a limited time.
I could create a little jar-file which will delete the data manually, probably started as a cron-job. But i think, that that is a very bad solution.
Is it possible to create a trigger with JPA/Java EE that will be called after a specific time period? As far as i know trigger can only be called after/before insert, update, delete events. So that won't be a solution.
Note: I'm currently using H2-Database and Wildfly for my RESTeasy application. But i might change that in future, so the solution should be adaptive.
Best regards,
Maik
Java EE brings everything you need. You can #Schedule a periodically executed cleanup job:
#Singleton
public class Cleanup {
#Schedule(minute = "*/5")
public void clean() {
// will be called every 5 minutes
}
}
Or you programmatically create a Timer which will be executed after a certain amount of time:
#Singleton
public class Cleanup {
#Resource
TimerService timerService;
public void deleteLater(long id) {
String timerInfo = MyEntity.class.getName() + ':' + id;
long timeout = 1000 * 60 * 5; // 5 minutes
timerService.createTimer(timeout, timerInfo);
}
#Timeout
public void handleTimeout(Timer timer) {
Serializable timerInfo = timer.getInfo(); // the information you passed to the timer
}
}
More information can be found in the Timer Service Tutorial.

CQ5(CRX) bookstore application error

I checked out source code fromhttp://dev.day.com/docs/en/crx/current/getting_started/first_steps_with_crx.html#Step%20Two:%20Check%20out%20CRX%20Bookstore%20Example
When I tried to invoke http://:4502/products.html
Actual result should list the products page from bookstore app
I got "Cannot serve request to /products.html in /apps/bookstore/components/ranking/ranking.jsp: What version of the product are you using? On what operating system?
I am using CQ5.5 (CRX 2.3) on windows 7
http://code.google.com/p/crxzon/issues/detail?id=4&thanks=4&ts=1362987616
From what I see, you get NullPointerException in RankingServiceImpl:277, because the repository field is null. And the only way I can explain that is that SCR annotations didn't fire during the build.
Said that, I'm actually surprised your bundle started on CQ 5.5, as the dependencies seem to be to earlier versions (5.4 I guess) -- I suggest double checking that under /system/console/bundles (search for CRX - Sample Bookstore Demo). If you're missing imports there, try playing with /src/impl/com.day.crx.sample.bookshop.bnd to update versions as in CQ 5.5, or running it on CQ 5.4.
The annotations in RankingServiceImpl seem to be for an earlier version of CQ and CRX. Here are the changes that I made to get this to work:
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
/**
* Default implementation of the ranking service.
* The ranking is updated through observation (based on OSGi events).
* The service can be used by clients to get the highest ranked products.
*/
#Component(immediate = true)
#Service(value = RankingService.class)
#Property(name = org.osgi.service.event.EventConstants.EVENT_TOPIC, value = SlingConstants.TOPIC_RESOURCE_ADDED)
public class RankingServiceImpl
implements RankingService, EventHandler, Runnable {
private Logger logger = LoggerFactory.getLogger(this.getClass());
// private Logger logger = LoggerFactory.getLogger("RankingServiceImpl");
private static final String PROPERTY_PREV_RANKING = "lowerRankingRef";
private static final String PROPERTY_NEXT_RANKING = "higherRankingRef";
private static final int SHOW_HIGHEST_RANKING = 3;
/** Flag for stopping the background service. */
private volatile boolean running = false;
/** A local queue for handling new orders. */
protected final BlockingQueue<String> orders = new LinkedBlockingQueue<String>();
#Reference
private SlingRepository repository;
#Reference
private ResourceResolverFactory resourceResolverFactory;

how to dig into this memory leak with eclipse MAT further

I have an issue where a ScheduledThreadPoolExecutor ends up with 3 million future tasks. I am trying to see what type of task so I can go to where that task is scheduled, but I am not sure how to get any info from this screen(I have tried right clicking those future tasks and selecting various choices in the menu). It seems like there is something missing in the gui like the links to the actual runnables or something...
any ideas on how to drill into further?
Some General Stuff
You need to know, that if you have a portable heap dump (phd, see types here), then it does not contain actual data (primitives), so then you can make your findings only based on reference map (which types hold a reference to which other types).
You can give a try to OQL. This is an SQL like language, with which you can query your objects.
One example:
select * from java.lang.String s where s.#retainedHeapSize>10000
This gives back all strings, that are bigger than ~10k.
You can make also some functions (like this aggregating here).
You could give a try to it.
As for the current problem
If you check the FutureTask source (here is JDK6 below):
public class FutureTask<V> implements RunnableFuture<V> {
/** Synchronization control for FutureTask */
private final Sync sync;
...
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);
}
...
public FutureTask(Runnable runnable, V result) {
sync = new Sync(Executors.callable(runnable, result));
}
The actual Runnable is referred by the Sync object:
private final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -7828117401763700385L;
/** State value representing that task is running */
private static final int RUNNING = 1;
/** State value representing that task ran */
private static final int RAN = 2;
/** State value representing that task was cancelled */
private static final int CANCELLED = 4;
/** The underlying callable */
private final Callable<V> callable;
/** The result to return from get() */
private V result;
/** The exception to throw from get() */
private Throwable exception;
/**
* The thread running task. When nulled after set/cancel, this
* indicates that the results are accessible. Must be
* volatile, to ensure visibility upon completion.
*/
private volatile Thread runner;
Sync(Callable<V> callable) {
this.callable = callable;
}
So in the GUI open the Sync object (not open in your picture), and then you can check the Runnables.
I dont know if you can change the code or not, but in general it is better always limit the size of the queue used by an executor, since this way you can avoid leaks. Or you can use some persisted queue. If you apply a limit you can define the rejection policy like for example reject, run in caller and so on. See http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html for details.