Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find Jobs by Tag #32

Open
kingargyle opened this issue Jul 7, 2015 · 8 comments
Open

Find Jobs by Tag #32

kingargyle opened this issue Jul 7, 2015 · 8 comments

Comments

@kingargyle
Copy link

Is there a way to find jobs by tag from the JobManager?

Basically I need to know if a job has already been added to the job queue for a particular tag so I don't add another one. Jobs could be queued up waiting for network state to come back on line and when it does I don't need two of the same job for the same tag being run.

@yigit
Copy link
Owner

yigit commented Jul 8, 2015

Sorry we don't have an API for that. You can simply implement concurrent string set which holds the tags and the job sets one when it is created and removes when it is done or canceled.

Also, I think you should re-think that logic. For instance, if a job is about to run and you are trying to add a new one, what is the desired behavior? Do you really want them to run one after another ? I feel like what you really want is some sort of delay between jobs (which you still need to implement manually).

You can also consider first calling cancel and depending on the result, enqueue another job or not.

@kingargyle
Copy link
Author

Actually, I just want one of the jobs for a particular tag to run. I don't necessarily want to add another one in the queue, particularly if the device is offline and doesn't have network activity. I may have several jobs of various tags in a queue, but don't necessarily want to add multiple jobs of the same tag type to the queue that are waiting to be run as it can cause some inconsitencies in the web services that are invoked by the job resulting in some inconsistent states.

While I can manually keep track of it myself, if the JobManager already knows about the jobs it has queued and waiting for network activity to be restored, it would make sense to be able to find or check to see how many jobs of a particular tag may already be in the queue waiting to be executed.

@max-was-here
Copy link

I have a workaround to do this until simpler API are available. You need to override the default queue factory and add getters to the internal CachedJobQueue :

public class CustomQueueFactory implements QueueFactory {
    private SqliteJobQueue.JobSerializer jobSerializer;

    private CachedJobQueue persistentJobQueue;
    private CachedJobQueue nonPersistentJobQueue;

    CustomQueueFactory(){
        this(new SqliteJobQueue.JavaSerializer());
    }

    CustomQueueFactory(SqliteJobQueue.JobSerializer jobSerializer) {
        this.jobSerializer = jobSerializer;
    }

    CachedJobQueue getPersistentJobQueue() {
        return persistentJobQueue;
    }

    CachedJobQueue getNonPersistentJobQueue() {
        return nonPersistentJobQueue;
    }

    @Override
    public JobQueue createPersistentQueue(Context context, Long sessionId, String id, boolean inTestMode) {
        this.persistentJobQueue = new CachedJobQueue(new SqliteJobQueue(context, sessionId, id, jobSerializer,inTestMode));
        return persistentJobQueue;
    }

    @Override
    public JobQueue createNonPersistent(Context context, Long sessionId, String id, boolean inTestMode) {
        this.nonPersistentJobQueue = new CachedJobQueue(new NonPersistentPriorityQueue(sessionId, id, inTestMode));
        return nonPersistentJobQueue;
    }
}

You can then use the queues and call findJobsByTags :

CustomQueueFactory queueFactory = new CustomQueueFactory();
JobManager jobManager = new JobManager(context,
                new Configuration.Builder(context)
                .queueFactory(queueFactory)
                .build()
);
CachedJobQueue jobQueue = queueFactory.getPersistentJobQueue();
Set<JobHolder> jobs = jobQueue.findJobsByTags(TagConstraint.ANY, true, null, "my_awesome_tag");
// findJobsByTags(TagConstraint constraint, boolean excludeCancelled, Collection<Long> exclude, String... tags)

@tgbarker
Copy link

This workaround no longer works and is what I was using prior to 2.0.0 . (findJobsByTags no longer exists, Constraint has no constructor) My use case is I simply want to expose a list of the jobs in the queue. I use the priority job queue for queueing network requests, if the device isn't connected to the internet, then the jobs are queued without sending and I wish to expose this to the user that these messages haven't yet been sent.

Why was this removed in 2.0.0? I saw some chatter about race conditions on stackoverflow, ok, but I would suggest my usecase is valid to display the messages that havent been sent to the user. I simply want to access the list of jobs in the queue. This, especially since it worked in previous versions....

@yigit
Copy link
Owner

yigit commented Aug 24, 2016

I suggest doing this using a JobManagerCallback where you can keep track of jobs.
Alternatively, you can just override the Constraint to make setTags method public like I do in the test:
https://github.com/yigit/android-priority-jobqueue/blob/ba693a35e22753e8a9050a9ad572d4b2b9959467/jobqueue/src/test/java/com/birbit/android/jobqueue/TestConstraint.java

It is just not a public API so might change but probably wont.

@max-was-here
Copy link

max-was-here commented Aug 24, 2016

Opening the API up would really help to customize the usage of the library for our needs.
For now, here is my new workaround

MyQueueFactory.java

class MyQueueFactory implements QueueFactory {
    private final SqliteJobQueue.JobSerializer jobSerializer;

    private CachedJobQueue persistentJobQueue;
    private CachedJobQueue nonPersistentJobQueue;

    MyQueueFactory(){
        this(new SqliteJobQueue.JavaSerializer());
    }

    MyQueueFactory(SqliteJobQueue.JobSerializer jobSerializer) {
        this.jobSerializer = jobSerializer;
    }

    CachedJobQueue getPersistentJobQueue() {
        return persistentJobQueue;
    }

    CachedJobQueue getNonPersistentJobQueue() {
        return nonPersistentJobQueue;
    }


    @Override
    public JobQueue createPersistentQueue(Configuration configuration, long sessionId) {
        this.persistentJobQueue = new CachedJobQueue(new SqliteJobQueue(configuration, sessionId, jobSerializer));
        return persistentJobQueue;
    }

    @Override
    public JobQueue createNonPersistent(Configuration configuration, long sessionId) {
        this.nonPersistentJobQueue = new CachedJobQueue(new SimpleInMemoryPriorityQueue(configuration, sessionId));
        return nonPersistentJobQueue;
    }
}

MyConstraint.java

class MyConstraint extends Constraint{
    @Override
    public int getMaxNetworkType() {
        // My jobs require network so I had to override this filter
        return NetworkUtil.METERED;
    }

    @Override
    public Set<String> getTags() {
        HashSet<String> tagsList = new HashSet<>();
        // Here you can filter by tags
        tagsList.add("MY_JOB_TAG");
        return tagsList;
    }
}

MyJobManager.java

public class MyJobManager {
    private static final MyJobManager instance = new MyJobManager();

    private final JobManager jobManager;
    private final MyQueueFactory queueFactory;

    private MyJobManager(){
        this.queueFactory = new MyQueueFactory();
        this.jobManager = new JobManager(new Configuration.Builder(MyApp.getAppContext())
                .id("MyJobManager")
                .queueFactory(this.queueFactory)
                .build());

        this.listeners = new ArrayList<>();
    }

    public static MyJobManager getInstance(){
        return MyJobManager.instance;
    }

    public void addJobInBackground(Job job){
        this.jobManager.addJobInBackground(job);
    }

    public List<Job> getPendingJobs(){
        ArrayList<Job> jobList = new ArrayList<>();

        CachedJobQueue jobQueue = this.queueFactory.getPersistentJobQueue();
        if(jobQueue != null){
            // Here we use our Constraint override to filter the jobs.
            Set<JobHolder> jobs = jobQueue.findJobs(new MyConstraint());

            for(JobHolder jobHolder: jobs){
                Job job = jobHolder.getJob();

                if(job != null){
                    jobList.add(job);
                }
            }
        }

        return jobList;
    }
}

@tgbarker
Copy link

Thanks titouef, I had done the same minus the NetworkUtil.METERED and bizarrely didn't work, with that override it does, I added the getMaxNetworkType and works as before, using this workaround.

Hi yigit, great lib, thank you. The setTags can't be overriden, I'm outside the package bar I copy paste everything into mine...

+1 for just opening up the API. Thanks

@aftabsikander
Copy link

+1 for just opening up the API. Thanks really great library

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants