Popular New Releases in Job Scheduling
resque
2.2.0
rq
v1.10.1
dolphinscheduler
3.0.0-alpha-release
shardingsphere-elasticjob
3.0.0
Hangfire
1.8.0-beta3
Popular Libraries in Job Scheduling
by mperham ruby
11744 NOASSERTION
Simple, efficient background processing for Ruby
by resque ruby
9071 MIT
Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later.
by dbader python
8936 MIT
Python job scheduling for humans.
by rq python
8211 NOASSERTION
Simple job queues for Python
by apache java
7656 Apache-2.0
Apache DolphinScheduler is a distributed and extensible workflow scheduler platform with powerful DAG visual interfaces, dedicated to solving complex job dependencies in the data pipeline and providing various types of jobs available out of box.
by apache java
7207 Apache-2.0
Distributed scheduled job framework
by HangfireIO csharp
6847 NOASSERTION
An easy way to perform background job processing in your .NET and .NET Core applications. No Windows Service or separate process required
by RichardKnop go
5525 MPL-2.0
Machinery is an asynchronous task queue/job queue based on distributed message passing.
by evernote java
5375 Apache-2.0
Android library to handle jobs in the background.
Trending New libraries in Job Scheduling
by PowerJob java
3412 Apache-2.0
Enterprise job scheduling middleware with distributed computing ability.
by KFCFans java
2357 Apache-2.0
Enterprise job scheduling middleware with distributed computing ability.
by jobrunr java
864 NOASSERTION
An extremely easy way to perform background processing in Java. Backed by persistent storage. Open and free for commercial use.
by kubernetes-sigs go
427 Apache-2.0
Repository for out-of-tree scheduler plugins based on scheduler framework.
by Shopify ruby
398 MIT
A Rails engine for queueing and managing maintenance tasks for data migrations and backfills.
by hamadmarri c
210
The CacULE CPU scheduler is based on interactivity score mechanism. The interactivity score is inspired by the ULE scheduler (FreeBSD scheduler).
by maikebing csharp
195 MIT
SilkierQuartz can host jobs using HostService and Provide a web management tools for Quartz !
by hibiken typescript
174 MIT
Web UI for Asynq task queue
by smol-rs rust
163 NOASSERTION
Task abstraction for building executors
Top Authors in Job Scheduling
1
4 Libraries
15301
2
4 Libraries
1021
3
4 Libraries
355
4
4 Libraries
10999
5
3 Libraries
47
6
3 Libraries
10974
7
3 Libraries
833
8
3 Libraries
122
9
3 Libraries
7
10
3 Libraries
12
1
4 Libraries
15301
2
4 Libraries
1021
3
4 Libraries
355
4
4 Libraries
10999
5
3 Libraries
47
6
3 Libraries
10974
7
3 Libraries
833
8
3 Libraries
122
9
3 Libraries
7
10
3 Libraries
12
Trending Kits in Job Scheduling
Nodejs Scheduling Library is a library of functions and tools. It enables developers to create and manage automated tasks within an application. This library uses JavaScript to create applications. It will schedule and execute tasks at designated times. The library enables developers to schedule tasks in advance. It enables developers to run on a specific date and time or find the right times for running tasks. It also configures various task parameters, such as delays, intervals, and repetition. With Nodejs Scheduling, Library developers can create efficient applications and minimize resource usage.
Different types of nodejs scheduling available libraries:
- node-schedule: A fast, flexible, and lightweight job scheduling library for Node.js.
- Agenda: Agenda is a lightweight library for scheduling jobs in Node.js. It allows you to schedule jobs, run them on a specific schedule, and manage them.
- Cron-job.org: A cloud-based scheduler for Node.js. It is designed to make scheduling and running tasks in Node.js as easy and efficient as possible.
- Axiom Scheduler: A powerful library to schedule tasks both on the client and server side. It works by applying a rule-based approach to scheduling tasks.
- Timers.js: A library for setTimeout and setInterval functions. This is a vital choice for those who need a simpler approach to scheduling tasks in Node.js.
- Node-cron: A library that allows you to schedule tasks in Node.js using cron syntax. It is an excellent option when you are familiar with the cron syntax and want to use it in Node.
- Nodetime: A library for scheduling jobs in Node.js. It is designed for multi-threaded applications. It provides several features to make it easy to manage many jobs.
Different features are available in different nodejs scheduling libraries:
Time-Based Scheduling:
- Cron Syntax:
It helps execute tasks based on date and time.
- Schedule Once:
It helps execute a task at a specific point.
- Recurring:
It helps execute a task regularly (daily, weekly, etc.).
Event-Based Scheduling:
- Event-Based Actions:
It helps execute an action upon the occurrence of the specified event.
- Signal-Based Scheduling:
It helps execute tasks based on certain signals.
- System-Based Actions:
It helps execute tasks based on system events.
For using a nodejs scheduling library, one should:
- Evaluate the specific features of each library. Consider which library offers the functionality you need, whether concurrency, retrying, etc.
- Test out each library before committing to it. Many libraries provide sample codes or demos. It runs these tests, and comparing their performance is useful.
- Research the community resources that at each library. This can confirm whether the library is maintained and has good quality support.
- Explore the configuration options. Many libraries provide customization. You can tailor how it behaves to fit your specific needs.
- Consider the performance of the library. Make sure that any library you choose performs well. It can handle the scale at which you plan to use the scheduling library.
- Consider how each library handles errors and timeouts. We should handle errors and enforce timeouts.
- Seek good documentation. Libraries that provide good-quality documentation make integrating. It helps in configuring the library for your usage easier.
Different ways that a nodejs scheduling library can be used are:
- Automating Tasks:
A node.js scheduling library can create, execute, and manage scheduled tasks. For instance, you can use the scheduler to provide automated feedback. It helps users send out emails, run reports, or send notifications.
- Job Scheduling:
The scheduling library can schedule jobs for specific times and recurring tasks. This is useful when dealing with complex processes like backups or database updates.
- Process Control:
Node.js scheduling libraries also allow you to monitor process details. You can attach extra information like timing data and user-defined tasks. It will be helpful comments to process records. It can be useful for better process control and auditing.
- Job Scheduling:
Node.js scheduling libraries can schedule jobs for specific times and recurring tasks. This is useful for creating tasks that must be handled at certain times or regular intervals.
- Event-Based Processing:
The scalability and event-based processing capabilities of Node.js scheduling libraries. It makes them great for event-driven tasks, such as MySql polling or updates to a NoSQL database. You can use the library's events to trigger.
To use a nodejs scheduling library:
- Understand How Node Scheduling Libraries Work:
Before using a Node scheduling library, understand how it works. A Node scheduling library allows you to schedule tasks triggered at pre-determined intervals. This is for creating backups, running reports, cleaning up, or setting reminders. Familiarize yourself with the basic concepts. The concepts like creating tasks/timers, scheduling executions, and scheduling recurring events.
- Set Up Your Task Executors:
You must also set up your task executors when adding tasks to your library. A task executor handles running a particular task when subjected to a timer. You can choose from several task executor types, such as a function, a set of commands, a task or file, or a URL.
- Manage Your Timers:
You can manage your timers once you've set up your tasks and task executors. This includes setting up one-time jobs, recurring jobs, or creating cron-like schedules. You can also adjust your timing parameters. It includes an interval of execution, maximum number of executions, and maximum execution duration.
- Take Advantage of Advanced Features:
Many Node scheduling libraries offer advanced features. It offers task retries, priority settings, event handlers, and groupings. Take time to understand these features and take advantage of them. It helps ensure the reliability and accuracy of your scheduled tasks.
- Continuously Check Performance:
Finally, take time to monitor the performance of your task scheduler. This includes monitoring your tasks' accuracy. It helps ensure that your scheduled processes are running as possible. This will help ensure your tasks are running as expected. It also ensures that errors or missed executions are addressed.
Conclusion
Using a Node.js scheduling library is an attractive way. It helps developers to integrate scheduling capabilities into their applications. These libraries provide developers with an intuitive and powerful API. It helps schedule tasks, handle and trigger external events, and execute scheduled tasks.
The functionality supports them, which is ideal for scaling and making applications more powerful. It can couple external services and APIs with scheduling libraries. It gives developers the power to orchestrate complex and distributed events. It helps in handling local and remote triggers.
Node.js scheduling libraries are a powerful tool for developers. It helps incorporate scheduling into their applications. You can bring your applications to life with the right library in your toolbelt. You can do so with reliable and powerful scheduling capabilities.
cron
- It supports scheduling many jobs to run at the same time using wildcards.
- Can run jobs at any frequency, from minutes to years.
- Jobs can be set up and managed. It allows users to manage jobs in different environments from one location.
agenda
- Allows developers to add unique attributes to each job. It makes it easy for the application to customize jobs and data further.
- Backed by an active community of support, making it easy for developers to get help if needed.
- Built to be a data store. It means developers can store job-related information in a single, pre-configured database.
node-schedule
- Flexibility by enabling users to control scheduling parameters via code.
- Offers built-in real-time monitoring tools and an API for collecting job execution metrics.
- Allow you to set recurrences, create custom timeouts, and even run tasks in parallel.
node-cron
- A sophisticated runtime engine. It makes it easy to store past scheduled times. It helps execute tasks at the correct time even if the system clock is adjusted.
- Supports various scheduling modes, including intervals and cron expressions.
- Allows you to specify a callback for each job, allowing you to customize the jobs to different tasks.
Haraka
- Event-driven task scheduler. It allows developers to trigger tasks at a specified time or in intervals.
- Supports custom task parameters so that jobs can be customized to specific needs.
- It has a built-in logging infrastructure to track tasks.
buzzer
- It helps trigger node services. It allows you to link different components within your application and schedule related tasks.
- Provides an extensive API to customize tasks. This allows you to customize timing, retry settings, execution logic, and more.
- Includes scheduling features such as cron scheduling, creating on-demand tasks, and recurring schedules.
ontime
- Easy integration with external services through webhooks and plugins.
- Provides real-time updates on task progress. It allows tasks to be cron-style scheduled and triggered.
- Strong logging capabilities provide an audit trail of scheduled tasks, a feature differentiating it.
FAQ
What is the cron syntax for scheduling jobs with a node job scheduling library?
In general, the cron syntax for node job scheduling libraries is written in six fields:
[SECONDS] [MINUTES] [HOURS] [DAYS OF MONTH] [MONTH] [DAYS OF WEEK]
Each field can contain an asterisk (*). It represents any valid, comma-separated, or numbers represented by a hyphen. Additionally, a forward slash (/) can define step values.
How does a nodejs developer implement a job scheduling library into their roadmap?
A Node.js developer can implement a job scheduling library into their roadmap. The foremost step is to pick the appropriate library. Popular scheduling libraries for Node.js include Agenda and Later.js.
Once it is selected, the developer must install the library using a package manager. Then, depending on its options, they must set up the library's configuration. This may include setting up the job queue and configuring the scheduling interval.
The developer may need to create an interface to abstract the library and build methods to work. Once the interface is set up, the developer can create new jobs and schedule/execute tasks.
Finally, the developer may need to add monitoring capabilities and error handling. This will allow them to debug any issues with the job scheduling library.
What are the main features of Node scheduler, and how do they differ from Google Cloud Scheduler?
Node Scheduler is an npm package that allows you to add job scheduling in your Node.js applications. It supports various scheduling functions. It includes scheduling tasks in intervals, on specific dates, or at specified times. It can also perform tasks on a cron schedule and can be used to manage @reboot jobs.
The main features of the Node scheduler include the following:
- Flexible Scheduling:
It supports a variety of scheduling functions. It lets you define jobs as recurring tasks, perform tasks on a cron schedule, or execute @reboot jobs.
- High Availability:
The node scheduler is designed to be reliable and tolerant of system or server failures. Jobs will remain pending until they succeed.
- Ready API:
Node scheduler enables you to use its API to define, store, and manage jobs. It also allows you to access data about past runs. It enables easy integration with other services.
- Advanced Features:
It supports recurrent jobs, delay scheduling, time zone support, and automatic retries.
Google Cloud Scheduler is a service. It allows you to schedule jobs to run on Google Compute Engine or App Engine instances. Its main features include integration.
Are there any other cron implementations that are available for use in nodejs?
Yes! Also, to the standard cron library, some alternatives provide similar functionality. These include Agenda.js, node-cron, and node-schedule.
How can MongoDB be used to store data related to scheduled jobs?
MongoDB can store data related to scheduled jobs using its built-in scheduling mechanisms. This enables developers to store data related to events within the database. It can also track the progress and history of jobs. It allows developers to query and report on job performance and success. MongoDB can build efficient and distributed job queues. It will further allow developers to monitor and control the execution of jobs.
Is there a straightforward way to pause or stop a scheduling method?
Yes, pausing or stopping a scheduling method is possible. If you use a language such as Java, you can use the Timer and TimerTask classes to pause or stop a scheduling method.
What advantages does time-based scheduling have over the task triggering in node runtime?
Time-based scheduling has advantages over the manual triggering of tasks in node runtime. First, it reduces human error by automating the task execution process instead of relying on someone to remember to run a task on a specific day or time. Time-based scheduling ensures tasks are triggered when they need to be. Time-based scheduling also helps optimize system resources by running tasks at specific times. It happens when demand is expected to be lighter, and CPU use will be more optimal. Time-based scheduling helps reduce maintenance time by eliminating the need to trigger tasks. It can help predictability and reliability since tasks will always occur when scheduled.
Are there any security considerations when leveraging job scheduling libraries with my codebase?
Yes, there are a few security considerations. Considering this when leveraging these libraries with your project's codebase would be best.
- Ensure that you understand the library's authentication and authorization systems. Then, audit them for security vulnerabilities.
- Review the library for secure storage and authentication of parameters, credentials, and API keys.
- Ensure that appropriate logging is in place for any job-related activity.
- Set up regular vulnerability scanning of both the libraries and the codebase. It will ensure that no new vulnerabilities are introduced.
- Ensure that users and processes using job scheduling libraries have enough permissions. Then, only the minimum number of privileges are required to perform their activities.
- Follow best practices and use secure coding techniques to prevent malicious code injections.
What extra benefits does a job scheduling library provide? When compared to writing custom code for task execution within the runtime environment?
These libraries can provide various benefits over writing custom code for task execution. These benefits include the following:
- Automation:
A job scheduling library can manage task execution according to predefined schedules. This reduces the time spent coding and overseeing the execution of tasks.
- Scalability:
A job scheduling library can scale with your task load. It provides flexibility when dealing with different types of tasks and workloads.
- Efficiency:
A job scheduling library can execute many tasks, saving time and resources.
- Fault Tolerance:
A job scheduling library is designed to be robust in the face of failures and downtimes. The library can detect and recover from errors and failures. It will help reduce the consequence of any potential downtime.
- Cost Savings:
A job scheduling library can reduce the cost of labor. It will reduce the cost associated with manual coding and overseeing task execution.
Trending Discussions on Job Scheduling
building a jar library from a war project using maven?
Can Python be invoked against a script file with a parameter-name for the script filepath?
Is there a way to ignore some machines (set to nothing) in job shop scheduling problem?
best way to export bigquery table with nested columns into csv file
How to keep job schedule data in database for Quartz Scheduler
impossible to start the onStartJob method
How to schedule a Hangfire background job on a specific time AND in a specific queue?
Mainframe: How to prevent DB2 contention between batch job and CICS transaction?
JobService to fire Notification by using Switch widget on Android
Automatic page refresh stops working (Flask App)
QUESTION
building a jar library from a war project using maven?
Asked 2022-Feb-28 at 18:50We have a EAR project which has a WAR project. Maven is used, so pom.xml. As typical of any project, this project also contains a big feature (say Job Scheduling "JBS") among many other features. As it is planned to retire this whole project in the near future, it is discouraged heavily to spend much on working on this project (whether bugs or enhancements).
Therefore, for the sake of running the (JBS) feature as a separate application, the whole EAR project was duplicated (also to save time/cost). As a result, all the Java packages and classes (necessary for JBS project) were duplicated. In this situation, if we update one or more classes in the main project, this (JBS) feature project/application gets outdated (and needs update).
The fact is that this JBS feature project ONLY requires many packages of Java classes (from the main EAR-WAR project), and do not require 99% of the web modules and others. I am removing all the unnecessary things from JBS project. Then I would like to create a JAR library with all the java classes, so JBS project can have a dependency on this JAR.
I do not know if it is a good idea to separate these classes out of the main project (to create another Java project). I would like to continue to have these classes as part of the main project. Then, it will be good, as and when one or more of these classes are changed, a new version of the JAR will be generated (right away). And the JBS project would then make use of this updated JAR.
How can we accomplish this? I understand, through maven, we can do a build/package jar/war/ear on a project of that nature. I am not an expert with maven (and did not learn it systematically).
But, is there a way to create one or more JARs additionally from inside WAR pom.xml? In other words: I mean pom.xml of WAR will create a WAR. In addition to creating a WAR, can maven help create additional JAR? Or can maven create two packages out of one pom.xml?
Or should I create a separate module in the main project with all these packages/classes, and have its own pom.xml to generate the necessary JAR? For this, most probably I need to modify the structure of the main project. I would like to avoid this unless there is no way out.
Can you advice?
ANSWER
Answered 2022-Feb-28 at 18:50It seems like the best thing for you would be to create a multi-module project that both contains the JAR and the other project. This way, you can easily change/build them together, but you create separate artifacts.
QUESTION
Can Python be invoked against a script file with a parameter-name for the script filepath?
Asked 2022-Feb-21 at 20:40Does anyone know if the python3
command on Linux can have some sort of SOME_NAMED_OPTION=filename.py
after it rather than just calling python3 filename.py
?
I have a job scheduling tool I'd like to execute a Python script with that's kind of dumb.
It can only run Linux CLI commands commandname param1 param2 param3
or as commandname AAA=param1 BBB=param2 CCC=param3
.
There's an existing business convention of putting filename.py
as param #1 and then just making sure your script has a lot of comments about what the subsequent numerically ordered sys.argv
list members mean, and you set the scheduling tool into its first mode, so it runs python3 filename.py world mundo monde
, but it'd be awesome to be able to name the scheduling tool's parameters #2+ so I can write more human-friendly Python programs.
With python3 -h
I'm not finding a way to give a parameter-name to filename.py
, but I thought I'd see if anyone else had done it and I'm just missing it.
It'd be cool if I could have my scheduling tool run the a command more like python3 --scriptsource=filename.py --salut=monde --hola=mundo --hello=world
and then write filename.py
to use argparse to grab hola
's, hello
's, and salut
's values by name instead of by position.
ANSWER
Answered 2022-Feb-21 at 20:39You can create a python file to be executed as a script like in the example bellow:
1 #!/usr/bin/python3 # path to python in your system
2
3 print('This is a script!')
4
If your python file is named test.py you can execute as ./test.py if the file has permission to be executed. To grant execution permission to your file use the command chmod +x test.py
QUESTION
Is there a way to ignore some machines (set to nothing) in job shop scheduling problem?
Asked 2021-Dec-16 at 22:21I am working on a job scheduling program with the objective of reducing makespan that involves scheduling multiple jobs on multiple machines, where:
- The same job cannot operate on different machines at the same time
- Only one job can process at a given time on a given machine
However, I'd like to add a constraint that some machines may not be needed to process a particular job. As shown below, for the list of machine elements, job 1 can occur on machine 0 and 2, but doesn't need to go through machine 1 (it can skip this machine). To designate the null, I added np.nan. (Note: If you insert either 0, 1, or 2 here in place of np.nan, this entire code will run without errors.)
Here is my code so far:
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63
But I'm running into an error at this line:
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66
Which says:
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67
Is it not possible to insert a missing value into the machine list for this type of Mixed Integer program? Or will a simple update to this line of code suffice?
As another attempt, I tried to add None
instead of np.nan
and this returned the error:
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67TypeError: list indices must be integers or slices, not NoneType
68
ANSWER
Answered 2021-Dec-16 at 20:44I think there are a couple issues in your formulation (for the model without any excluded machines). It runs/solves with a zero value for me, so I'm not sure what result your are getting. But that is a separate issue.
If you want to "exclude" some machines within the context of some jobs, I think you need to do a bit more work on the indexing. Specifically, if you were to write out "the math" for some constraints, you would be doing something like "for each job-machine pair that exists in the plan make some constraint..." So, the way I would approach this is to build subsets (as needed) to only include valid starts. An example below. Note also, I like using the LpVariaible.dicts
method to create vars. I think it is cleaner, and then you can tuple-index them because they are held in a dictionary.
And lastly, some consistency in nomenclature will help readability! You have i,j,k,m,n
when I think you can probably tackle this with j, j_prime, m, ...
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67TypeError: list indices must be integers or slices, not NoneType
68from pulp import *
69
70# define number of machines (m) and jobs (j)
71machines = 3
72jobs = 2
73
74# for each job, the order the machines will go in
75# for job 1, machine 1 is not needed
76machine_sequence = [[0, None, 2],
77 [1, 2, 0 ]]
78
79valid_starts = [(j, m) for j in range(jobs) for m in range(machines) if machine_sequence[j][m] != None]
80
81model = LpProblem("Example", LpMinimize)
82
83# Improved Variable...? using LpVariable.dicts
84s = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
85
86# starting time x, on job j (from all jobs n) on machine i (from all machines m)
87x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(machines)] for j in range(jobs)]
88
89print(type(s), s)
90print(type(x), x)
91
92# random constraint for j-m pairs that are valid
93for j, m in valid_starts:
94 model += s[j, m] <= 10
95
I tinkered a bit more with this. Turns out with your data the way that you have it, it is easier to remove the "None" in the machine sequence, because you will need to iterate through that sequence. Preserving it in the times works just to position the times in the right spot. A different data structure (dictionaries) might lead to a different approach.
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67TypeError: list indices must be integers or slices, not NoneType
68from pulp import *
69
70# define number of machines (m) and jobs (j)
71machines = 3
72jobs = 2
73
74# for each job, the order the machines will go in
75# for job 1, machine 1 is not needed
76machine_sequence = [[0, None, 2],
77 [1, 2, 0 ]]
78
79valid_starts = [(j, m) for j in range(jobs) for m in range(machines) if machine_sequence[j][m] != None]
80
81model = LpProblem("Example", LpMinimize)
82
83# Improved Variable...? using LpVariable.dicts
84s = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
85
86# starting time x, on job j (from all jobs n) on machine i (from all machines m)
87x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(machines)] for j in range(jobs)]
88
89print(type(s), s)
90print(type(x), x)
91
92# random constraint for j-m pairs that are valid
93for j, m in valid_starts:
94 model += s[j, m] <= 10
95from pulp import *
96
97# define model
98schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
99
100# define number of machines (m) and jobs (j)
101machines = 3
102jobs = 2
103
104# for each job, the order the machines will go in
105# for job 1, machine 1 is not needed
106machine_sequence = [[0, 2],
107 [1, 2, 0 ]]
108
109# for each job, the processing time of each
110times = [[2, None, 3],
111 [1, 4, 5]]
112
113valid_starts = [(j, m) for j in range(jobs) for m in machine_sequence[j]]
114
115# x[j, m] = start time for job j on machine m
116x = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
117
118# machine sequence constraint
119# for each machine in the job sequence (except the 0th), the start time of the
120# machine must be greater than the previous start + duration
121for j in range(jobs): # for each job
122 for m_idx in range(1, len(machine_sequence[j])): # for each machine in job's seq, except 0
123 # convenience for bookkeeping...
124 curr_machine = machine_sequence[j][m_idx]
125 prior_machine = machine_sequence[j][m_idx - 1]
126
127 # so,
128 schedule += x[j, curr_machine] >= x[j, prior_machine] + times[j][prior_machine]
129
130print(schedule)
131
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67TypeError: list indices must be integers or slices, not NoneType
68from pulp import *
69
70# define number of machines (m) and jobs (j)
71machines = 3
72jobs = 2
73
74# for each job, the order the machines will go in
75# for job 1, machine 1 is not needed
76machine_sequence = [[0, None, 2],
77 [1, 2, 0 ]]
78
79valid_starts = [(j, m) for j in range(jobs) for m in range(machines) if machine_sequence[j][m] != None]
80
81model = LpProblem("Example", LpMinimize)
82
83# Improved Variable...? using LpVariable.dicts
84s = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
85
86# starting time x, on job j (from all jobs n) on machine i (from all machines m)
87x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(machines)] for j in range(jobs)]
88
89print(type(s), s)
90print(type(x), x)
91
92# random constraint for j-m pairs that are valid
93for j, m in valid_starts:
94 model += s[j, m] <= 10
95from pulp import *
96
97# define model
98schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
99
100# define number of machines (m) and jobs (j)
101machines = 3
102jobs = 2
103
104# for each job, the order the machines will go in
105# for job 1, machine 1 is not needed
106machine_sequence = [[0, 2],
107 [1, 2, 0 ]]
108
109# for each job, the processing time of each
110times = [[2, None, 3],
111 [1, 4, 5]]
112
113valid_starts = [(j, m) for j in range(jobs) for m in machine_sequence[j]]
114
115# x[j, m] = start time for job j on machine m
116x = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
117
118# machine sequence constraint
119# for each machine in the job sequence (except the 0th), the start time of the
120# machine must be greater than the previous start + duration
121for j in range(jobs): # for each job
122 for m_idx in range(1, len(machine_sequence[j])): # for each machine in job's seq, except 0
123 # convenience for bookkeeping...
124 curr_machine = machine_sequence[j][m_idx]
125 prior_machine = machine_sequence[j][m_idx - 1]
126
127 # so,
128 schedule += x[j, curr_machine] >= x[j, prior_machine] + times[j][prior_machine]
129
130print(schedule)
131Minimize_Schedule:
132MINIMIZE
133None
134SUBJECT TO
135_C1: - start_time_(0,_0) + start_time_(0,_2) >= 2
136
137_C2: - start_time_(1,_1) + start_time_(1,_2) >= 4
138
139_C3: start_time_(1,_0) - start_time_(1,_2) >= 5
140
141VARIABLES
142start_time_(0,_0) Continuous
143start_time_(0,_2) Continuous
144start_time_(1,_0) Continuous
145start_time_(1,_1) Continuous
146start_time_(1,_2) Continuous
147
The below is a completed model that runs and (seems to) produce correct answers.
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67TypeError: list indices must be integers or slices, not NoneType
68from pulp import *
69
70# define number of machines (m) and jobs (j)
71machines = 3
72jobs = 2
73
74# for each job, the order the machines will go in
75# for job 1, machine 1 is not needed
76machine_sequence = [[0, None, 2],
77 [1, 2, 0 ]]
78
79valid_starts = [(j, m) for j in range(jobs) for m in range(machines) if machine_sequence[j][m] != None]
80
81model = LpProblem("Example", LpMinimize)
82
83# Improved Variable...? using LpVariable.dicts
84s = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
85
86# starting time x, on job j (from all jobs n) on machine i (from all machines m)
87x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(machines)] for j in range(jobs)]
88
89print(type(s), s)
90print(type(x), x)
91
92# random constraint for j-m pairs that are valid
93for j, m in valid_starts:
94 model += s[j, m] <= 10
95from pulp import *
96
97# define model
98schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
99
100# define number of machines (m) and jobs (j)
101machines = 3
102jobs = 2
103
104# for each job, the order the machines will go in
105# for job 1, machine 1 is not needed
106machine_sequence = [[0, 2],
107 [1, 2, 0 ]]
108
109# for each job, the processing time of each
110times = [[2, None, 3],
111 [1, 4, 5]]
112
113valid_starts = [(j, m) for j in range(jobs) for m in machine_sequence[j]]
114
115# x[j, m] = start time for job j on machine m
116x = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
117
118# machine sequence constraint
119# for each machine in the job sequence (except the 0th), the start time of the
120# machine must be greater than the previous start + duration
121for j in range(jobs): # for each job
122 for m_idx in range(1, len(machine_sequence[j])): # for each machine in job's seq, except 0
123 # convenience for bookkeeping...
124 curr_machine = machine_sequence[j][m_idx]
125 prior_machine = machine_sequence[j][m_idx - 1]
126
127 # so,
128 schedule += x[j, curr_machine] >= x[j, prior_machine] + times[j][prior_machine]
129
130print(schedule)
131Minimize_Schedule:
132MINIMIZE
133None
134SUBJECT TO
135_C1: - start_time_(0,_0) + start_time_(0,_2) >= 2
136
137_C2: - start_time_(1,_1) + start_time_(1,_2) >= 4
138
139_C3: start_time_(1,_0) - start_time_(1,_2) >= 5
140
141VARIABLES
142start_time_(0,_0) Continuous
143start_time_(0,_2) Continuous
144start_time_(1,_0) Continuous
145start_time_(1,_1) Continuous
146start_time_(1,_2) Continuous
147# makespan model for jobs with sequence of machine requirements
148# that may exclude some machines
149
150from pulp import *
151
152# define model
153schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
154
155# define number of machines (m) and jobs (j)
156machines = 3
157jobs = 2
158
159# for each job, the order the machines will go in
160# for job 1, machine 1 is not needed
161machine_sequence = [[0, 2],
162 [1, 2, 0 ]]
163
164# for each job, the processing time on required machines
165times = [[2, None, 3],
166 [1, 4, 5]]
167M=100
168valid_starts = [(j, m) for j in range(jobs) for m in machine_sequence[j]]
169
170# a convenience set that we will use later... job-job'-machine combos
171# for jobs that both compete for the same machine
172jjm = [(j, j_prime, m)
173 for j in range(jobs)
174 for j_prime in range(jobs)
175 for m in range(machines)
176 if j != j_prime
177 and (j, m) in valid_starts
178 and (j_prime, m) in valid_starts]
179
180# x[j, m] = start time for job j on machine m
181x = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
182# y[j, j_prime, m] = indicator that job j precedes j_prime on machine m
183y = LpVariable.dicts("precedence", indexs=jjm, cat='Binary')
184# makespan variable to capture the longest makespan
185c = LpVariable("makespan", lowBound=0, cat='Continuous')
186
187
188####### machine sequence constraint #######
189# for each machine in the job sequence (except the 0th), the start time of the
190# machine must be greater than the previous start + duration
191for j in range(jobs): # for each job
192 for m_idx in range(1, len(machine_sequence[j])): # for each machine in job's seq, except 0
193 # convenience for bookkeeping...
194 curr_machine = machine_sequence[j][m_idx]
195 prior_machine = machine_sequence[j][m_idx - 1]
196
197 # so,
198 schedule += x[j, curr_machine] >= x[j, prior_machine] + times[j][prior_machine]
199
200####### single-use constraint (jobs can't be on same machine at same time) #######
201for j, j_prime, m in jjm:
202 # if y, job j precedes j_prime, if not, use big M
203 schedule += x[j, m] + times[j][m] <= x[j_prime, m] + (1-y[j, j_prime, m])*M
204
205 # one or the other case below must be true...
206 # aside: this is lazy as it will produce duplicates,
207 # but the solver will remove them
208 schedule += y[j, j_prime, m] + y[j_prime, j, m] == 1
209
210####### constraint to capture the longest makespan #######
211schedule += c # put the obj into model
212for j, m in valid_starts: # for every job started on every machine...
213 schedule += c >= x[j, m] + times[j][m] # capture the latest finish time
214#print(schedule)
215
216status = schedule.solve()
217
218print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
219print("Completion time: ", schedule.objective.value())
220
221for j, m in valid_starts:
222 if x[j, m].varValue >= 0:
223 print("job %d starts on machine %d at time %g" % (j, m, x[j, m].varValue))
224
1from pulp import *
2import pandas as pd
3import numpy as np
4import collections as cl
5from itertools import product
6
7# define model
8schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
9
10# define number of machines (m) and jobs (n)
11m = 3
12n = 3
13
14# for each job, the processing time of each
15times = [[2, 1, 2],
16 [1, 2, 2],
17 [1, 2, 1]]
18
19# for each job, the order the machines will go in
20# for job 1, machine 1 is not needed
21machines = [[0, np.nan, 2],
22 [1, 2, 0],
23 [2, 1, 0]]
24
25# variables
26
27# objective function to minimize (the makespan)
28c = LpVariable(name="C")
29# starting time x, on job j (from all jobs n) on machine i (from all machines m)
30x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(m)] for j in range(n)]
31# y is a binary, where 1, if job j precedes job k on machine i; else 0
32y = [[[LpVariable(name='y({} ,{} ,{} )'.format(j+1, k+1, i+1), cat="Binary") for i in range(m)] for k in range(n)] for j in range(n)]
33
34# sum of total time for all machines (m) and jobs (n)
35M = sum(times[i][j] for i in range(n) for j in range(m))
36
37# add objective function to schedule model
38schedule += c
39
40# job j can only begin after job i has been completed
41for (j, i) in product(range(n), range(1, m)):
42 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
43
44# same jobs cannot occur at same time
45for (j, k) in product(range(n), range(n)):
46 if k != j:
47 for i in range(m):
48 schedule += x[j][i] - x[k][i] + M*y[j][k][i] >= times[k][i]
49 schedule += -x[j][i] + x[k][i] - M*y[j][k][i] >= times[j][i] - M
50
51
52for j in range(n):
53 schedule += c - x[j][machines[j][m-1]] >= times[j][machines[j][m-1]]
54
55status = schedule.solve()
56
57print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
58print("Completion time: ", schedule.objective.value())
59
60for i,j in product(range(m),range(n)):
61 if x[i][j].varValue >= 0:
62 print("job %d starts on machine %d at time %g" % (i+1, j+1, x[i][j].varValue))
63# job j can only begin after job i has been completed
64for (j, i) in product(range(n), range(1, m)):
65 schedule += x[j][machines[j][i]] - x[j][machines[j][i-1]] >= times[j][machines[j][i-1]]
66TypeError: list indices must be integers or slices, not float
67TypeError: list indices must be integers or slices, not NoneType
68from pulp import *
69
70# define number of machines (m) and jobs (j)
71machines = 3
72jobs = 2
73
74# for each job, the order the machines will go in
75# for job 1, machine 1 is not needed
76machine_sequence = [[0, None, 2],
77 [1, 2, 0 ]]
78
79valid_starts = [(j, m) for j in range(jobs) for m in range(machines) if machine_sequence[j][m] != None]
80
81model = LpProblem("Example", LpMinimize)
82
83# Improved Variable...? using LpVariable.dicts
84s = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
85
86# starting time x, on job j (from all jobs n) on machine i (from all machines m)
87x = [[LpVariable(name='x({} ,{} )'.format(j+1, i+1), lowBound=0) for i in range(machines)] for j in range(jobs)]
88
89print(type(s), s)
90print(type(x), x)
91
92# random constraint for j-m pairs that are valid
93for j, m in valid_starts:
94 model += s[j, m] <= 10
95from pulp import *
96
97# define model
98schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
99
100# define number of machines (m) and jobs (j)
101machines = 3
102jobs = 2
103
104# for each job, the order the machines will go in
105# for job 1, machine 1 is not needed
106machine_sequence = [[0, 2],
107 [1, 2, 0 ]]
108
109# for each job, the processing time of each
110times = [[2, None, 3],
111 [1, 4, 5]]
112
113valid_starts = [(j, m) for j in range(jobs) for m in machine_sequence[j]]
114
115# x[j, m] = start time for job j on machine m
116x = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
117
118# machine sequence constraint
119# for each machine in the job sequence (except the 0th), the start time of the
120# machine must be greater than the previous start + duration
121for j in range(jobs): # for each job
122 for m_idx in range(1, len(machine_sequence[j])): # for each machine in job's seq, except 0
123 # convenience for bookkeeping...
124 curr_machine = machine_sequence[j][m_idx]
125 prior_machine = machine_sequence[j][m_idx - 1]
126
127 # so,
128 schedule += x[j, curr_machine] >= x[j, prior_machine] + times[j][prior_machine]
129
130print(schedule)
131Minimize_Schedule:
132MINIMIZE
133None
134SUBJECT TO
135_C1: - start_time_(0,_0) + start_time_(0,_2) >= 2
136
137_C2: - start_time_(1,_1) + start_time_(1,_2) >= 4
138
139_C3: start_time_(1,_0) - start_time_(1,_2) >= 5
140
141VARIABLES
142start_time_(0,_0) Continuous
143start_time_(0,_2) Continuous
144start_time_(1,_0) Continuous
145start_time_(1,_1) Continuous
146start_time_(1,_2) Continuous
147# makespan model for jobs with sequence of machine requirements
148# that may exclude some machines
149
150from pulp import *
151
152# define model
153schedule = LpProblem(name="Minimize_Schedule", sense=LpMinimize)
154
155# define number of machines (m) and jobs (j)
156machines = 3
157jobs = 2
158
159# for each job, the order the machines will go in
160# for job 1, machine 1 is not needed
161machine_sequence = [[0, 2],
162 [1, 2, 0 ]]
163
164# for each job, the processing time on required machines
165times = [[2, None, 3],
166 [1, 4, 5]]
167M=100
168valid_starts = [(j, m) for j in range(jobs) for m in machine_sequence[j]]
169
170# a convenience set that we will use later... job-job'-machine combos
171# for jobs that both compete for the same machine
172jjm = [(j, j_prime, m)
173 for j in range(jobs)
174 for j_prime in range(jobs)
175 for m in range(machines)
176 if j != j_prime
177 and (j, m) in valid_starts
178 and (j_prime, m) in valid_starts]
179
180# x[j, m] = start time for job j on machine m
181x = LpVariable.dicts("start time", indexs=valid_starts, lowBound=0, cat='Continuous')
182# y[j, j_prime, m] = indicator that job j precedes j_prime on machine m
183y = LpVariable.dicts("precedence", indexs=jjm, cat='Binary')
184# makespan variable to capture the longest makespan
185c = LpVariable("makespan", lowBound=0, cat='Continuous')
186
187
188####### machine sequence constraint #######
189# for each machine in the job sequence (except the 0th), the start time of the
190# machine must be greater than the previous start + duration
191for j in range(jobs): # for each job
192 for m_idx in range(1, len(machine_sequence[j])): # for each machine in job's seq, except 0
193 # convenience for bookkeeping...
194 curr_machine = machine_sequence[j][m_idx]
195 prior_machine = machine_sequence[j][m_idx - 1]
196
197 # so,
198 schedule += x[j, curr_machine] >= x[j, prior_machine] + times[j][prior_machine]
199
200####### single-use constraint (jobs can't be on same machine at same time) #######
201for j, j_prime, m in jjm:
202 # if y, job j precedes j_prime, if not, use big M
203 schedule += x[j, m] + times[j][m] <= x[j_prime, m] + (1-y[j, j_prime, m])*M
204
205 # one or the other case below must be true...
206 # aside: this is lazy as it will produce duplicates,
207 # but the solver will remove them
208 schedule += y[j, j_prime, m] + y[j_prime, j, m] == 1
209
210####### constraint to capture the longest makespan #######
211schedule += c # put the obj into model
212for j, m in valid_starts: # for every job started on every machine...
213 schedule += c >= x[j, m] + times[j][m] # capture the latest finish time
214#print(schedule)
215
216status = schedule.solve()
217
218print(f"status: {schedule.status}, {LpStatus[schedule.status]}")
219print("Completion time: ", schedule.objective.value())
220
221for j, m in valid_starts:
222 if x[j, m].varValue >= 0:
223 print("job %d starts on machine %d at time %g" % (j, m, x[j, m].varValue))
224status: 1, Optimal
225Completion time: 11.0
226job 0 starts on machine 0 at time 0
227job 0 starts on machine 2 at time 2
228job 1 starts on machine 1 at time 0
229job 1 starts on machine 2 at time 5
230job 1 starts on machine 0 at time 10
231
QUESTION
best way to export bigquery table with nested columns into csv file
Asked 2021-Dec-10 at 06:23Friends,
I am trying to export BigQuery table with nested columns (Array, Struct) into CSV file by flattening the rows.
I have tried bq export
and Python BQ API (from google.cloud import bigquery
), both options.
Which approach would be better with respect to network performance and job scheduling ?
I was thinking of scheduling a job either on Scheduler or on Composer, which will run the export script to write csv file on cloud storage.
I know that bq export
requires cloud sdk, whereas Python BQ API is suitable with Cloud Function. But trying to understand which approach is best w.r.t to performance. Is there any recommendation ?
Also any link related to them would be helpful.
Regards, Sant
ANSWER
Answered 2021-Dec-10 at 06:23There is no major difference in performance between the two. bq export
and Python BQ API are both written in Python, and they are both calling the same BigQuery REST APIs behind the scenes.
The main difference is whether you are writing a command line script vs writing a Python script. Composer has both python_operator and bash_operator to work with either script. So this is just a matter of programming language choice/preference.
QUESTION
How to keep job schedule data in database for Quartz Scheduler
Asked 2021-Sep-25 at 20:05Currently, we have our job scheduling data stored in the database table. This allows the business user to alter the schedule in the database table through a customised screen. We are planning to migrate our scheduling framework to quartz. I have gone through the quartz documentation, it does not have anything to cover this requirement. Basically, if the schedule is changed, subsequent runs after the schedule job would be continued as per the new schedule, and this can happen without the restart.
ANSWER
Answered 2021-Sep-25 at 20:05can reschedule the existing quartz trigger
Using this method http://www.quartz-scheduler.org/api/2.3.0/org/quartz/Scheduler.html#rescheduleJob-org.quartz.TriggerKey-org.quartz.Trigger-
QUESTION
impossible to start the onStartJob method
Asked 2021-Sep-22 at 14:34I have the following code:
MainActivity.java
1package com.example.bluejob;
2
3import android.support.v7.app.AppCompatActivity;
4import android.os.Bundle;
5import android.app.job.JobInfo;
6import android.app.job.JobScheduler;
7import android.content.ComponentName;
8import android.util.Log;
9import android.view.View;
10
11
12public class MainActivity extends AppCompatActivity {
13 private static final String TAG = "MainActivity";
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_main);
18 }
19 public void scheduleJob(View v) {
20 ComponentName componentName = new ComponentName(this, BlueJobM.class);
21 JobInfo info = new JobInfo.Builder(821, componentName)
22 .setRequiresCharging(true)
23 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
24 .setPersisted(true)
25 .setPeriodic(15 * 60 * 1000)
26 .build();
27
28
29 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
30 int resultCode;
31 resultCode = scheduler.schedule(info);
32 if (resultCode == JobScheduler.RESULT_SUCCESS) {
33 Log.d(TAG, "Job scheduled");
34 } else {
35 Log.d(TAG, "Job scheduling failed");
36 }
37 }
38
39 public void cancelJob(View v) {
40 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
41 scheduler.cancel(821);
42 Log.d(TAG, "Job cancelled");
43 }
44}
45
OnStartJob method in BlueJobM.java
1package com.example.bluejob;
2
3import android.support.v7.app.AppCompatActivity;
4import android.os.Bundle;
5import android.app.job.JobInfo;
6import android.app.job.JobScheduler;
7import android.content.ComponentName;
8import android.util.Log;
9import android.view.View;
10
11
12public class MainActivity extends AppCompatActivity {
13 private static final String TAG = "MainActivity";
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_main);
18 }
19 public void scheduleJob(View v) {
20 ComponentName componentName = new ComponentName(this, BlueJobM.class);
21 JobInfo info = new JobInfo.Builder(821, componentName)
22 .setRequiresCharging(true)
23 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
24 .setPersisted(true)
25 .setPeriodic(15 * 60 * 1000)
26 .build();
27
28
29 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
30 int resultCode;
31 resultCode = scheduler.schedule(info);
32 if (resultCode == JobScheduler.RESULT_SUCCESS) {
33 Log.d(TAG, "Job scheduled");
34 } else {
35 Log.d(TAG, "Job scheduling failed");
36 }
37 }
38
39 public void cancelJob(View v) {
40 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
41 scheduler.cancel(821);
42 Log.d(TAG, "Job cancelled");
43 }
44}
45@Override
46 public boolean onStartJob(JobParameters params) {
47 Log.d(TAG, "Job started");
48 doBackgroundWork(params);
49
50 return true;
51 }
52
When I start the code on my Redmi I revive di series of errors:
1package com.example.bluejob;
2
3import android.support.v7.app.AppCompatActivity;
4import android.os.Bundle;
5import android.app.job.JobInfo;
6import android.app.job.JobScheduler;
7import android.content.ComponentName;
8import android.util.Log;
9import android.view.View;
10
11
12public class MainActivity extends AppCompatActivity {
13 private static final String TAG = "MainActivity";
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_main);
18 }
19 public void scheduleJob(View v) {
20 ComponentName componentName = new ComponentName(this, BlueJobM.class);
21 JobInfo info = new JobInfo.Builder(821, componentName)
22 .setRequiresCharging(true)
23 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
24 .setPersisted(true)
25 .setPeriodic(15 * 60 * 1000)
26 .build();
27
28
29 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
30 int resultCode;
31 resultCode = scheduler.schedule(info);
32 if (resultCode == JobScheduler.RESULT_SUCCESS) {
33 Log.d(TAG, "Job scheduled");
34 } else {
35 Log.d(TAG, "Job scheduling failed");
36 }
37 }
38
39 public void cancelJob(View v) {
40 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
41 scheduler.cancel(821);
42 Log.d(TAG, "Job cancelled");
43 }
44}
45@Override
46 public boolean onStartJob(JobParameters params) {
47 Log.d(TAG, "Job started");
48 doBackgroundWork(params);
49
50 return true;
51 }
522021-09-22 15:33:56.527 21306-21306/com.example.bluejob E/AndroidRuntime: FATAL EXCEPTION: main
53 Process: com.example.bluejob, PID: 21306
54 java.lang.IllegalStateException: Could not execute method for android:onClick
55 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
56 at android.view.View.performClick(View.java:6608)
57 at android.view.View.performClickInternal(View.java:6585)
58 at android.view.View.access$3100(View.java:785)
59 at android.view.View$PerformClick.run(View.java:25921)
60 at android.os.Handler.handleCallback(Handler.java:873)
61 at android.os.Handler.dispatchMessage(Handler.java:99)
62 at android.os.Looper.loop(Looper.java:201)
63 at android.app.ActivityThread.main(ActivityThread.java:6810)
64 at java.lang.reflect.Method.invoke(Native Method)
65 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
66 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
67 Caused by: java.lang.reflect.InvocationTargetException
68 at java.lang.reflect.Method.invoke(Native Method)
69 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
70 at android.view.View.performClick(View.java:6608)
71 at android.view.View.performClickInternal(View.java:6585)
72 at android.view.View.access$3100(View.java:785)
73 at android.view.View$PerformClick.run(View.java:25921)
74 at android.os.Handler.handleCallback(Handler.java:873)
75 at android.os.Handler.dispatchMessage(Handler.java:99)
76 at android.os.Looper.loop(Looper.java:201)
77 at android.app.ActivityThread.main(ActivityThread.java:6810)
78 at java.lang.reflect.Method.invoke(Native Method)
79 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
80 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
81 Caused by: java.lang.IllegalArgumentException: No such service ComponentInfo{com.example.bluejob/com.example.bluejob.BlueJobM}
82 at android.os.Parcel.createException(Parcel.java:1957)
83 at android.os.Parcel.readException(Parcel.java:1921)
84 at android.os.Parcel.readException(Parcel.java:1871)
85 at android.app.job.IJobScheduler$Stub$Proxy.schedule(IJobScheduler.java:184)
86 at android.app.JobSchedulerImpl.schedule(JobSchedulerImpl.java:44)
87
88
89 "I THINK THE ERROR IS HERE" at com.example.bluejob.MainActivity.scheduleJob(MainActivity.java:32)
90
91
92 at java.lang.reflect.Method.invoke(Native Method)
93 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
94 at android.view.View.performClick(View.java:6608)
95 at android.view.View.performClickInternal(View.java:6585)
96 at android.view.View.access$3100(View.java:785)
97 at android.view.View$PerformClick.run(View.java:25921)
98 at android.os.Handler.handleCallback(Handler.java:873)
99 at android.os.Handler.dispatchMessage(Handler.java:99)
100 at android.os.Looper.loop(Looper.java:201)
101 at android.app.ActivityThread.main(ActivityThread.java:6810)
102 at java.lang.reflect.Method.invoke(Native Method)
103 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
104 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
105 Caused by: android.os.RemoteException: Remote stack trace:
106 at com.android.server.job.JobSchedulerService$JobSchedulerStub.enforceValidJobRequest(JobSchedulerService.java:2538)
107 at com.android.server.job.JobSchedulerService$JobSchedulerStub.schedule(JobSchedulerService.java:2600)
108 at android.app.job.IJobScheduler$Stub.onTransact(IJobScheduler.java:60)
109 at android.os.Binder.execTransact(Binder.java:735)
110
When I start the App I can enter in the CancelJob method which correctly calls onStopJob on BlueJobM.java (i can see the log). When I remove this part of code form MainActivity.java
1package com.example.bluejob;
2
3import android.support.v7.app.AppCompatActivity;
4import android.os.Bundle;
5import android.app.job.JobInfo;
6import android.app.job.JobScheduler;
7import android.content.ComponentName;
8import android.util.Log;
9import android.view.View;
10
11
12public class MainActivity extends AppCompatActivity {
13 private static final String TAG = "MainActivity";
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_main);
18 }
19 public void scheduleJob(View v) {
20 ComponentName componentName = new ComponentName(this, BlueJobM.class);
21 JobInfo info = new JobInfo.Builder(821, componentName)
22 .setRequiresCharging(true)
23 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
24 .setPersisted(true)
25 .setPeriodic(15 * 60 * 1000)
26 .build();
27
28
29 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
30 int resultCode;
31 resultCode = scheduler.schedule(info);
32 if (resultCode == JobScheduler.RESULT_SUCCESS) {
33 Log.d(TAG, "Job scheduled");
34 } else {
35 Log.d(TAG, "Job scheduling failed");
36 }
37 }
38
39 public void cancelJob(View v) {
40 JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
41 scheduler.cancel(821);
42 Log.d(TAG, "Job cancelled");
43 }
44}
45@Override
46 public boolean onStartJob(JobParameters params) {
47 Log.d(TAG, "Job started");
48 doBackgroundWork(params);
49
50 return true;
51 }
522021-09-22 15:33:56.527 21306-21306/com.example.bluejob E/AndroidRuntime: FATAL EXCEPTION: main
53 Process: com.example.bluejob, PID: 21306
54 java.lang.IllegalStateException: Could not execute method for android:onClick
55 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
56 at android.view.View.performClick(View.java:6608)
57 at android.view.View.performClickInternal(View.java:6585)
58 at android.view.View.access$3100(View.java:785)
59 at android.view.View$PerformClick.run(View.java:25921)
60 at android.os.Handler.handleCallback(Handler.java:873)
61 at android.os.Handler.dispatchMessage(Handler.java:99)
62 at android.os.Looper.loop(Looper.java:201)
63 at android.app.ActivityThread.main(ActivityThread.java:6810)
64 at java.lang.reflect.Method.invoke(Native Method)
65 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
66 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
67 Caused by: java.lang.reflect.InvocationTargetException
68 at java.lang.reflect.Method.invoke(Native Method)
69 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
70 at android.view.View.performClick(View.java:6608)
71 at android.view.View.performClickInternal(View.java:6585)
72 at android.view.View.access$3100(View.java:785)
73 at android.view.View$PerformClick.run(View.java:25921)
74 at android.os.Handler.handleCallback(Handler.java:873)
75 at android.os.Handler.dispatchMessage(Handler.java:99)
76 at android.os.Looper.loop(Looper.java:201)
77 at android.app.ActivityThread.main(ActivityThread.java:6810)
78 at java.lang.reflect.Method.invoke(Native Method)
79 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
80 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
81 Caused by: java.lang.IllegalArgumentException: No such service ComponentInfo{com.example.bluejob/com.example.bluejob.BlueJobM}
82 at android.os.Parcel.createException(Parcel.java:1957)
83 at android.os.Parcel.readException(Parcel.java:1921)
84 at android.os.Parcel.readException(Parcel.java:1871)
85 at android.app.job.IJobScheduler$Stub$Proxy.schedule(IJobScheduler.java:184)
86 at android.app.JobSchedulerImpl.schedule(JobSchedulerImpl.java:44)
87
88
89 "I THINK THE ERROR IS HERE" at com.example.bluejob.MainActivity.scheduleJob(MainActivity.java:32)
90
91
92 at java.lang.reflect.Method.invoke(Native Method)
93 at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
94 at android.view.View.performClick(View.java:6608)
95 at android.view.View.performClickInternal(View.java:6585)
96 at android.view.View.access$3100(View.java:785)
97 at android.view.View$PerformClick.run(View.java:25921)
98 at android.os.Handler.handleCallback(Handler.java:873)
99 at android.os.Handler.dispatchMessage(Handler.java:99)
100 at android.os.Looper.loop(Looper.java:201)
101 at android.app.ActivityThread.main(ActivityThread.java:6810)
102 at java.lang.reflect.Method.invoke(Native Method)
103 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
104 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
105 Caused by: android.os.RemoteException: Remote stack trace:
106 at com.android.server.job.JobSchedulerService$JobSchedulerStub.enforceValidJobRequest(JobSchedulerService.java:2538)
107 at com.android.server.job.JobSchedulerService$JobSchedulerStub.schedule(JobSchedulerService.java:2600)
108 at android.app.job.IJobScheduler$Stub.onTransact(IJobScheduler.java:60)
109 at android.os.Binder.execTransact(Binder.java:735)
110 int resultCode;
111 resultCode = scheduler.schedule(info);
112 if (resultCode == JobScheduler.RESULT_SUCCESS) {
113 Log.d(TAG, "Job scheduled");
114 } else {
115 Log.d(TAG, "Job scheduling failed");
116 }
117
the error does not show up but the job doesn't start anyway. I suspect the program has some problem building the Job but I'm not sure.
I put more code on Github if is needed https://github.com/jaxis/BlueJob.
I was following this tutorial soo the code should be similar to this one https://www.youtube.com/watch?v=3EQWmME-hNA&t .
Thanks in advance.
ANSWER
Answered 2021-Sep-22 at 14:19java.lang.IllegalArgumentException: No such service ComponentInfo{com.example.bluejob/com.example.bluejob.BlueJobM}
That means it doesn't know anything about that class as a component. Generally this means you didn't add it to the manifest. Every Service and Activity you want to use needs to be in the manifest. In some cases BroadcastReceivers do as well (although not all).
QUESTION
How to schedule a Hangfire background job on a specific time AND in a specific queue?
Asked 2021-Jun-10 at 18:28I use Hangfire for scheduling jobs. In my setup I have defined two distinct queues. One is used to process recurrent jobs and jobs with a 'low' priority. The other queue is used for jobs that have a 'high' priority which are created ad hoc resulting from user input. Non recurrent jobs are scheduled like this to ensure they end up in the correct queue:
1var client = new BackgroundJobClient();
2var state = new EnqueuedState(queueName);
3client.Create(methodCall, state);
4
All works fine, but now I have a new requirement where I need to delay execution for 'high priority' jobs under certain conditions.
I found this question here on Stack Overflow which mentions the BackgroundJobClient.Schedule operation accepts an enqueueAt parameter:
1var client = new BackgroundJobClient();
2var state = new EnqueuedState(queueName);
3client.Create(methodCall, state);
4var client = new BackgroundJobClient();
5client.Schedule(methodCall, enqueueAt);
6
Unfortunately this Schedule operation does not provide me with an option to define the queue. Jobs scheduled using this approach end up in the 'default' queue of Hangfire. Any idea how I can implement the job scheduling delay together with having the ability to determine the queue at runtime?
ANSWER
Answered 2021-Jun-10 at 18:28You can use an argument that defines the queue name for methodCall
. Based on discussion here, you can selectively run the method on queue of your choice. UseQueueFromParameter
should solve the issue you are facing
QUESTION
Mainframe: How to prevent DB2 contention between batch job and CICS transaction?
Asked 2021-Jun-09 at 09:57I have a batch job and a CICS transaction that use the same db2 tables. Both run at regular intervals and the batch job abends once in a while due to contention with the shared DB2 tables.
Is there a way to schedule the job in CA7 (job scheduling tool) to prevent it from running when the transaction is active?
ANSWER
Answered 2021-Jun-08 at 14:21- Disable the CICS transaction before starting the batch job, re-enable it when the batch job ends.
- Modify the batch job to use commit intervals, similar to this answer.
Checking to see if the CICS transaction is active is unlikely to behave as you wish. It may be inactive when you check, then you start your batch job, then the CICS transaction becomes active.
Update #1
Though you don't specify, I'm getting the impression this is a long-running CICS transaction and not the normal OLTP-style transaction that finishes in less than 0.10 seconds of clock time.
If this is the case, then creating a batch program that uses the EXCI to execute a CICS program that uses the CICS SPI INQUIRE TASKLIST to locate your transaction may be the way to proceed. If you've got CA-DADs PLUS then you might be able to do this with that product instead of writing programs.
QUESTION
JobService to fire Notification by using Switch widget on Android
Asked 2021-May-03 at 11:15I have an app with a Switch
that has to fire my JobService
. I called two methods in setOnCheckedChangeListener
of the Switch, one for register and one for unregister the job.
It seems to work, like debug shows, but the the background work inside the onStartJob
. What am I missing?
MemoNotificationService.kt
1class MemoNotificationService : JobService() {
2
3 companion object {
4 const val TAG = "MemoPush"
5 const val serviceId = 4242
6 }
7
8
9 override fun onStartJob(params: JobParameters?): Boolean {
10 doBackgroundWork(params)
11 return true
12 }
13
14 private fun doBackgroundWork(params: JobParameters?) {
15 CoroutineScope(Dispatchers.IO).launch {
16 Log.d(TAG, "Push sending...")
17 sendNotification("body push 1", "title push 1", "", 1)
18 Log.d(TAG, "Push sent")
19 jobFinished(params, false)
20 }
21 }
22
23 override fun onStopJob(params: JobParameters?): Boolean {
24 Log.d(TAG, "<Job interrupt>")
25 return true
26 }
27
28
29 fun sendNotification(
30 messageBody: String,
31 messageTitle: String,
32 largeIconPath: String,
33 pushId: Int
34 ) {
35
36 val channelId = getString(R.string.consumer_notification_channel_id)
37 val channelName = getString(R.string.consumer_notification_channel_name)
38 val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
39 val notificationBuilder = NotificationCompat.Builder(this, channelId)
40 .setSmallIcon(R.drawable.logo_anim1)
41 .setColor(ContextCompat.getColor(this, R.color.colorAccent))
42 .setColorized(true)
43 .setContentTitle(messageTitle)
44 .setContentText(messageBody)
45 .setAutoCancel(true)
46 .setSound(defaultSoundUri)
47 .setLights(Color.YELLOW, 1000, 1000)
48
49
50 val notificationManager =
51 getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
52
53 // Since android Oreo notification channel is needed.
54 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
55 val channel = NotificationChannel(
56 channelId,
57 channelName,
58 NotificationManager.IMPORTANCE_DEFAULT
59 )
60 channel.enableLights(true)
61 channel.lightColor = Color.YELLOW
62 notificationManager.createNotificationChannel(channel)
63 }
64
65 notificationManager.notify(pushId, notificationBuilder.build())
66 }
67
68
69}
70
SettingsFragment.kt
1class MemoNotificationService : JobService() {
2
3 companion object {
4 const val TAG = "MemoPush"
5 const val serviceId = 4242
6 }
7
8
9 override fun onStartJob(params: JobParameters?): Boolean {
10 doBackgroundWork(params)
11 return true
12 }
13
14 private fun doBackgroundWork(params: JobParameters?) {
15 CoroutineScope(Dispatchers.IO).launch {
16 Log.d(TAG, "Push sending...")
17 sendNotification("body push 1", "title push 1", "", 1)
18 Log.d(TAG, "Push sent")
19 jobFinished(params, false)
20 }
21 }
22
23 override fun onStopJob(params: JobParameters?): Boolean {
24 Log.d(TAG, "<Job interrupt>")
25 return true
26 }
27
28
29 fun sendNotification(
30 messageBody: String,
31 messageTitle: String,
32 largeIconPath: String,
33 pushId: Int
34 ) {
35
36 val channelId = getString(R.string.consumer_notification_channel_id)
37 val channelName = getString(R.string.consumer_notification_channel_name)
38 val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
39 val notificationBuilder = NotificationCompat.Builder(this, channelId)
40 .setSmallIcon(R.drawable.logo_anim1)
41 .setColor(ContextCompat.getColor(this, R.color.colorAccent))
42 .setColorized(true)
43 .setContentTitle(messageTitle)
44 .setContentText(messageBody)
45 .setAutoCancel(true)
46 .setSound(defaultSoundUri)
47 .setLights(Color.YELLOW, 1000, 1000)
48
49
50 val notificationManager =
51 getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
52
53 // Since android Oreo notification channel is needed.
54 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
55 val channel = NotificationChannel(
56 channelId,
57 channelName,
58 NotificationManager.IMPORTANCE_DEFAULT
59 )
60 channel.enableLights(true)
61 channel.lightColor = Color.YELLOW
62 notificationManager.createNotificationChannel(channel)
63 }
64
65 notificationManager.notify(pushId, notificationBuilder.build())
66 }
67
68
69}
70private fun registerNotification() {
71 //TODO("Not yet implemented")
72 val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
73 val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
74 .setPersisted(true) /*persist on boot*/ /*not sure if needed*/
75 .setPeriodic(30 * 1000) /*once a day = 24 * 60 * 60 * 1000 */
76 .build()
77 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
78 val resultCode = scheduler.schedule(info)
79 if(resultCode == JobScheduler.RESULT_SUCCESS)
80 Log.d(MemoNotificationService.TAG, "<Job scheduled>")
81 else
82 Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
83 }
84
85private fun unregisterNotification() {
86 //TODO("Not yet implemented")
87 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
88 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelling> :: ${scheduler.allPendingJobs}")
89 scheduler.cancel(MemoNotificationService.serviceId)
90 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelled> :: ${scheduler.allPendingJobs}")
91 }
92
AndroidManifest.xml
1class MemoNotificationService : JobService() {
2
3 companion object {
4 const val TAG = "MemoPush"
5 const val serviceId = 4242
6 }
7
8
9 override fun onStartJob(params: JobParameters?): Boolean {
10 doBackgroundWork(params)
11 return true
12 }
13
14 private fun doBackgroundWork(params: JobParameters?) {
15 CoroutineScope(Dispatchers.IO).launch {
16 Log.d(TAG, "Push sending...")
17 sendNotification("body push 1", "title push 1", "", 1)
18 Log.d(TAG, "Push sent")
19 jobFinished(params, false)
20 }
21 }
22
23 override fun onStopJob(params: JobParameters?): Boolean {
24 Log.d(TAG, "<Job interrupt>")
25 return true
26 }
27
28
29 fun sendNotification(
30 messageBody: String,
31 messageTitle: String,
32 largeIconPath: String,
33 pushId: Int
34 ) {
35
36 val channelId = getString(R.string.consumer_notification_channel_id)
37 val channelName = getString(R.string.consumer_notification_channel_name)
38 val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
39 val notificationBuilder = NotificationCompat.Builder(this, channelId)
40 .setSmallIcon(R.drawable.logo_anim1)
41 .setColor(ContextCompat.getColor(this, R.color.colorAccent))
42 .setColorized(true)
43 .setContentTitle(messageTitle)
44 .setContentText(messageBody)
45 .setAutoCancel(true)
46 .setSound(defaultSoundUri)
47 .setLights(Color.YELLOW, 1000, 1000)
48
49
50 val notificationManager =
51 getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
52
53 // Since android Oreo notification channel is needed.
54 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
55 val channel = NotificationChannel(
56 channelId,
57 channelName,
58 NotificationManager.IMPORTANCE_DEFAULT
59 )
60 channel.enableLights(true)
61 channel.lightColor = Color.YELLOW
62 notificationManager.createNotificationChannel(channel)
63 }
64
65 notificationManager.notify(pushId, notificationBuilder.build())
66 }
67
68
69}
70private fun registerNotification() {
71 //TODO("Not yet implemented")
72 val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
73 val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
74 .setPersisted(true) /*persist on boot*/ /*not sure if needed*/
75 .setPeriodic(30 * 1000) /*once a day = 24 * 60 * 60 * 1000 */
76 .build()
77 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
78 val resultCode = scheduler.schedule(info)
79 if(resultCode == JobScheduler.RESULT_SUCCESS)
80 Log.d(MemoNotificationService.TAG, "<Job scheduled>")
81 else
82 Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
83 }
84
85private fun unregisterNotification() {
86 //TODO("Not yet implemented")
87 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
88 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelling> :: ${scheduler.allPendingJobs}")
89 scheduler.cancel(MemoNotificationService.serviceId)
90 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelled> :: ${scheduler.allPendingJobs}")
91 }
92<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
93...
94<service
95
96 android:name=".MemoNotificationService"
97 android:permission="android.permission.BIND_JOB_SERVICE" />
98
Logcat
1class MemoNotificationService : JobService() {
2
3 companion object {
4 const val TAG = "MemoPush"
5 const val serviceId = 4242
6 }
7
8
9 override fun onStartJob(params: JobParameters?): Boolean {
10 doBackgroundWork(params)
11 return true
12 }
13
14 private fun doBackgroundWork(params: JobParameters?) {
15 CoroutineScope(Dispatchers.IO).launch {
16 Log.d(TAG, "Push sending...")
17 sendNotification("body push 1", "title push 1", "", 1)
18 Log.d(TAG, "Push sent")
19 jobFinished(params, false)
20 }
21 }
22
23 override fun onStopJob(params: JobParameters?): Boolean {
24 Log.d(TAG, "<Job interrupt>")
25 return true
26 }
27
28
29 fun sendNotification(
30 messageBody: String,
31 messageTitle: String,
32 largeIconPath: String,
33 pushId: Int
34 ) {
35
36 val channelId = getString(R.string.consumer_notification_channel_id)
37 val channelName = getString(R.string.consumer_notification_channel_name)
38 val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
39 val notificationBuilder = NotificationCompat.Builder(this, channelId)
40 .setSmallIcon(R.drawable.logo_anim1)
41 .setColor(ContextCompat.getColor(this, R.color.colorAccent))
42 .setColorized(true)
43 .setContentTitle(messageTitle)
44 .setContentText(messageBody)
45 .setAutoCancel(true)
46 .setSound(defaultSoundUri)
47 .setLights(Color.YELLOW, 1000, 1000)
48
49
50 val notificationManager =
51 getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
52
53 // Since android Oreo notification channel is needed.
54 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
55 val channel = NotificationChannel(
56 channelId,
57 channelName,
58 NotificationManager.IMPORTANCE_DEFAULT
59 )
60 channel.enableLights(true)
61 channel.lightColor = Color.YELLOW
62 notificationManager.createNotificationChannel(channel)
63 }
64
65 notificationManager.notify(pushId, notificationBuilder.build())
66 }
67
68
69}
70private fun registerNotification() {
71 //TODO("Not yet implemented")
72 val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
73 val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
74 .setPersisted(true) /*persist on boot*/ /*not sure if needed*/
75 .setPeriodic(30 * 1000) /*once a day = 24 * 60 * 60 * 1000 */
76 .build()
77 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
78 val resultCode = scheduler.schedule(info)
79 if(resultCode == JobScheduler.RESULT_SUCCESS)
80 Log.d(MemoNotificationService.TAG, "<Job scheduled>")
81 else
82 Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
83 }
84
85private fun unregisterNotification() {
86 //TODO("Not yet implemented")
87 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
88 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelling> :: ${scheduler.allPendingJobs}")
89 scheduler.cancel(MemoNotificationService.serviceId)
90 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelled> :: ${scheduler.allPendingJobs}")
91 }
92<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
93...
94<service
95
96 android:name=".MemoNotificationService"
97 android:permission="android.permission.BIND_JOB_SERVICE" />
98D/MemoPush: <Job scheduled>
99D/MemoPush: <Job scheduling cancelling> :: [(job:4242/com.example.testjobservice/.MemoNotificationService)]
100D/MemoPush: <Job scheduling cancelled> :: []
101
Actually I need to send push notifications with an offline service (no Internet in the entire application), once a day for example, with the same notification, or a list of... Is it the right way to achieve this?
ANSWER
Answered 2021-May-03 at 11:15Documentation says that minimum scheduler time is 15 minutes, so it would probably be the problem. Changing the code to:
SettingsFragment.kt
1class MemoNotificationService : JobService() {
2
3 companion object {
4 const val TAG = "MemoPush"
5 const val serviceId = 4242
6 }
7
8
9 override fun onStartJob(params: JobParameters?): Boolean {
10 doBackgroundWork(params)
11 return true
12 }
13
14 private fun doBackgroundWork(params: JobParameters?) {
15 CoroutineScope(Dispatchers.IO).launch {
16 Log.d(TAG, "Push sending...")
17 sendNotification("body push 1", "title push 1", "", 1)
18 Log.d(TAG, "Push sent")
19 jobFinished(params, false)
20 }
21 }
22
23 override fun onStopJob(params: JobParameters?): Boolean {
24 Log.d(TAG, "<Job interrupt>")
25 return true
26 }
27
28
29 fun sendNotification(
30 messageBody: String,
31 messageTitle: String,
32 largeIconPath: String,
33 pushId: Int
34 ) {
35
36 val channelId = getString(R.string.consumer_notification_channel_id)
37 val channelName = getString(R.string.consumer_notification_channel_name)
38 val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
39 val notificationBuilder = NotificationCompat.Builder(this, channelId)
40 .setSmallIcon(R.drawable.logo_anim1)
41 .setColor(ContextCompat.getColor(this, R.color.colorAccent))
42 .setColorized(true)
43 .setContentTitle(messageTitle)
44 .setContentText(messageBody)
45 .setAutoCancel(true)
46 .setSound(defaultSoundUri)
47 .setLights(Color.YELLOW, 1000, 1000)
48
49
50 val notificationManager =
51 getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
52
53 // Since android Oreo notification channel is needed.
54 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
55 val channel = NotificationChannel(
56 channelId,
57 channelName,
58 NotificationManager.IMPORTANCE_DEFAULT
59 )
60 channel.enableLights(true)
61 channel.lightColor = Color.YELLOW
62 notificationManager.createNotificationChannel(channel)
63 }
64
65 notificationManager.notify(pushId, notificationBuilder.build())
66 }
67
68
69}
70private fun registerNotification() {
71 //TODO("Not yet implemented")
72 val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
73 val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
74 .setPersisted(true) /*persist on boot*/ /*not sure if needed*/
75 .setPeriodic(30 * 1000) /*once a day = 24 * 60 * 60 * 1000 */
76 .build()
77 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
78 val resultCode = scheduler.schedule(info)
79 if(resultCode == JobScheduler.RESULT_SUCCESS)
80 Log.d(MemoNotificationService.TAG, "<Job scheduled>")
81 else
82 Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
83 }
84
85private fun unregisterNotification() {
86 //TODO("Not yet implemented")
87 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
88 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelling> :: ${scheduler.allPendingJobs}")
89 scheduler.cancel(MemoNotificationService.serviceId)
90 Log.d(MemoNotificationService.TAG, "<Job scheduling cancelled> :: ${scheduler.allPendingJobs}")
91 }
92<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
93...
94<service
95
96 android:name=".MemoNotificationService"
97 android:permission="android.permission.BIND_JOB_SERVICE" />
98D/MemoPush: <Job scheduled>
99D/MemoPush: <Job scheduling cancelling> :: [(job:4242/com.example.testjobservice/.MemoNotificationService)]
100D/MemoPush: <Job scheduling cancelled> :: []
101private fun registerNotification() {
102 val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
103 val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
104 .setPersisted(true)
105
106 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
107 //info.setPeriodic(24 * 60 * 60 * 1000,12 * 60 * 60 * 1000)
108 info.setPeriodic(30 * 60 * 1000,15 * 60 * 1000) //for testing purpose
109 }
110 else {
111 //info.setPeriodic(24 * 60 * 60 * 1000)
112 info.setPeriodic(15 * 60 * 1000) //for testing purpose
113 }
114
115 val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
116 val resultCode = scheduler.schedule(info.build())
117 if(resultCode == JobScheduler.RESULT_SUCCESS)
118 Log.d(MemoNotificationService.TAG, "<Job scheduled>")
119 else
120 Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
121}
122
it works like a charm, I guess.
Anyway, for further solutions, it's better to use WorkManager
that is built upon AlarmManager
(API < 21) and JobScheduler
(API >= 21).
Official codelab: https://developer.android.com/codelabs/android-workmanager?index=..%2F..index#0
QUESTION
Automatic page refresh stops working (Flask App)
Asked 2021-Feb-25 at 18:08I created a Flask app that displays the latest pictures on an HTML website. The website is set to automatically refresh every 10 seconds using a meta tag
1<meta http-equiv="refresh" content="10" />
2
it all works great when the server and website run on a local PC, but when I run the app over LAN, the page refreshes correctly a few times, but sooner or later it stops. The webpage itself looks like it is loading (spinning wheel), but no new requests are registered in the flask app. The only way to start refreshing it again is by manual refresh on the client-side or by restarting the flask app on the server-side.
What could be the problem that causes this and how to mitigate it? Can it be caused by a firewall that doesn't like the constant refreshes? Are there any alternatives to said meta tag? I don't want to have any difficult set-up on the client-side like job scheduling etc (unless it is the only solution).
ANSWER
Answered 2021-Feb-25 at 16:33You could just use javascript for this. Just put the code below in your html file somewhere or in a seperate javascript file named script.js
and link that javascript file like <script src="/Path/To/File.js"></script>
1<meta http-equiv="refresh" content="10" />
2<script>
3window.setTimeout(function () {
4 window.location.reload();
5}, 30000);
6</script>
7
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in Job Scheduling
Tutorials and Learning Resources are not available at this moment for Job Scheduling