Small improvements for jobs model and execution of jobs.
This commit is contained in:
parent
601960f5fb
commit
753af9d589
2 changed files with 364 additions and 44 deletions
|
@ -15,46 +15,83 @@ class Job < ApplicationModel
|
||||||
before_create :updated_matching, :update_next_run_at
|
before_create :updated_matching, :update_next_run_at
|
||||||
before_update :updated_matching, :update_next_run_at
|
before_update :updated_matching, :update_next_run_at
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
verify each job if needed to run (e. g. if true and times are matching) and execute it
|
||||||
|
|
||||||
|
Job.run
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
def self.run
|
def self.run
|
||||||
|
start_at = Time.zone.now
|
||||||
jobs = Job.where(active: true, running: false)
|
jobs = Job.where(active: true, running: false)
|
||||||
jobs.each do |job|
|
jobs.each do |job|
|
||||||
logger.debug "Execute job #{job.inspect}"
|
job.run(false, start_at)
|
||||||
|
|
||||||
next if !job.executable?
|
|
||||||
|
|
||||||
matching = job.matching_count
|
|
||||||
if job.matching != matching
|
|
||||||
job.matching = matching
|
|
||||||
job.save
|
|
||||||
end
|
|
||||||
|
|
||||||
next if !job.in_timeplan?
|
|
||||||
|
|
||||||
# find tickets to change
|
|
||||||
ticket_count, tickets = Ticket.selectors(job.condition, 2_000)
|
|
||||||
|
|
||||||
logger.debug "Job #{job.name} with #{ticket_count} tickets"
|
|
||||||
|
|
||||||
job.processed = ticket_count || 0
|
|
||||||
job.running = true
|
|
||||||
job.save
|
|
||||||
|
|
||||||
if tickets
|
|
||||||
tickets.each do |ticket|
|
|
||||||
Transaction.execute(disable_notification: job.disable_notification, reset_user_id: true) do
|
|
||||||
ticket.perform_changes(job.perform, 'job')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
job.running = false
|
|
||||||
job.last_run_at = Time.zone.now
|
|
||||||
job.save
|
|
||||||
end
|
end
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def executable?
|
=begin
|
||||||
|
|
||||||
|
execute a single job if needed (e. g. if true and times are matching)
|
||||||
|
|
||||||
|
job = Job.find(123)
|
||||||
|
|
||||||
|
job.run
|
||||||
|
|
||||||
|
force to run job (ignore times are matching)
|
||||||
|
|
||||||
|
job.run(true)
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def run(force = false, start_at = Time.zone.now)
|
||||||
|
logger.debug "Execute job #{inspect}"
|
||||||
|
|
||||||
|
if !executable?(start_at) && force == false
|
||||||
|
if next_run_at && next_run_at <= Time.zone.now
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
matching = matching_count
|
||||||
|
if self.matching != matching
|
||||||
|
self.matching = matching
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
|
||||||
|
if !in_timeplan?(start_at) && force == false
|
||||||
|
if next_run_at && next_run_at <= Time.zone.now
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# find tickets to change
|
||||||
|
ticket_count, tickets = Ticket.selectors(condition, 2_000)
|
||||||
|
|
||||||
|
logger.debug "Job #{name} with #{ticket_count} tickets"
|
||||||
|
|
||||||
|
self.processed = ticket_count || 0
|
||||||
|
self.running = true
|
||||||
|
save!
|
||||||
|
|
||||||
|
if tickets
|
||||||
|
tickets.each do |ticket|
|
||||||
|
Transaction.execute(disable_notification: disable_notification, reset_user_id: true) do
|
||||||
|
ticket.perform_changes(perform, 'job')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.running = false
|
||||||
|
self.last_run_at = Time.zone.now
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def executable?(start_at = Time.zone.now)
|
||||||
return false if !active
|
return false if !active
|
||||||
|
|
||||||
# only execute jobs, older then 1 min, to give admin posibility to change
|
# only execute jobs, older then 1 min, to give admin posibility to change
|
||||||
|
@ -62,7 +99,7 @@ class Job < ApplicationModel
|
||||||
|
|
||||||
# check if jobs need to be executed
|
# check if jobs need to be executed
|
||||||
# ignore if job was running within last 10 min.
|
# ignore if job was running within last 10 min.
|
||||||
return false if last_run_at && last_run_at > Time.zone.now - 10.minutes
|
return false if last_run_at && last_run_at > start_at - 10.minutes
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket1 = Ticket.create(
|
ticket1 = Ticket.create!(
|
||||||
title: 'job test 1',
|
title: 'job test 1',
|
||||||
group: group1,
|
group: group1,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -22,7 +22,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket2 = Ticket.create(
|
ticket2 = Ticket.create!(
|
||||||
title: 'job test 2',
|
title: 'job test 2',
|
||||||
group: group1,
|
group: group1,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -33,7 +33,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
updated_at: Time.zone.now - 1.day,
|
updated_at: Time.zone.now - 1.day,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket3 = Ticket.create(
|
ticket3 = Ticket.create!(
|
||||||
title: 'job test 3',
|
title: 'job test 3',
|
||||||
group: group2,
|
group: group2,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -44,7 +44,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
updated_at: Time.zone.now - 1.day,
|
updated_at: Time.zone.now - 1.day,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket4 = Ticket.create(
|
ticket4 = Ticket.create!(
|
||||||
title: 'job test 4',
|
title: 'job test 4',
|
||||||
group: group2,
|
group: group2,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -55,7 +55,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
updated_at: Time.zone.now - 3.days,
|
updated_at: Time.zone.now - 3.days,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket5 = Ticket.create(
|
ticket5 = Ticket.create!(
|
||||||
title: 'job test 5',
|
title: 'job test 5',
|
||||||
group: group2,
|
group: group2,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -249,7 +249,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'case 2' do
|
test 'with invalid state_id' do
|
||||||
|
|
||||||
# create ticket
|
# create ticket
|
||||||
group1 = Group.lookup(name: 'Users')
|
group1 = Group.lookup(name: 'Users')
|
||||||
|
@ -258,7 +258,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket1 = Ticket.create(
|
ticket1 = Ticket.create!(
|
||||||
title: 'job test 1',
|
title: 'job test 1',
|
||||||
group: group1,
|
group: group1,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -269,7 +269,7 @@ class JobTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
)
|
)
|
||||||
ticket2 = Ticket.create(
|
ticket2 = Ticket.create!(
|
||||||
title: 'job test 2',
|
title: 'job test 2',
|
||||||
group: group1,
|
group: group1,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -575,9 +575,8 @@ class JobTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'case 5' do
|
test 'check next_run_at' do
|
||||||
|
|
||||||
# create jobs
|
|
||||||
job1 = Job.create_or_update(
|
job1 = Job.create_or_update(
|
||||||
name: 'Test Job1',
|
name: 'Test Job1',
|
||||||
timeplan: {
|
timeplan: {
|
||||||
|
@ -644,6 +643,290 @@ class JobTest < ActiveSupport::TestCase
|
||||||
time_now = Time.zone.parse('2016-03-17 23:51:23 UTC')
|
time_now = Time.zone.parse('2016-03-17 23:51:23 UTC')
|
||||||
next_run_at = job1.next_run_at_calculate(time_now)
|
next_run_at = job1.next_run_at_calculate(time_now)
|
||||||
assert_equal('2016-03-21 00:00:00 UTC', next_run_at.to_s)
|
assert_equal('2016-03-21 00:00:00 UTC', next_run_at.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'update next run at' do
|
||||||
|
|
||||||
|
travel_to Time.zone.local(2017, 11, 10, 22, 0o4, 44)
|
||||||
|
|
||||||
|
job1 = Job.create_or_update(
|
||||||
|
name: 'Test Job1',
|
||||||
|
timeplan: {
|
||||||
|
days: {
|
||||||
|
Mon: false,
|
||||||
|
Tue: false,
|
||||||
|
Wed: false,
|
||||||
|
Thu: false,
|
||||||
|
Fri: false,
|
||||||
|
Sat: true,
|
||||||
|
Sun: false,
|
||||||
|
},
|
||||||
|
hours: {
|
||||||
|
'0' => false,
|
||||||
|
'1' => false,
|
||||||
|
'2' => false,
|
||||||
|
'3' => false,
|
||||||
|
'4' => false,
|
||||||
|
'5' => false,
|
||||||
|
'6' => false,
|
||||||
|
'7' => false,
|
||||||
|
'8' => false,
|
||||||
|
'9' => false,
|
||||||
|
'10' => false,
|
||||||
|
'11' => false,
|
||||||
|
'12' => false,
|
||||||
|
'13' => false,
|
||||||
|
'14' => false,
|
||||||
|
'15' => false,
|
||||||
|
'16' => false,
|
||||||
|
'17' => false,
|
||||||
|
'18' => false,
|
||||||
|
'19' => false,
|
||||||
|
'20' => false,
|
||||||
|
'21' => false,
|
||||||
|
'22' => false,
|
||||||
|
'23' => true,
|
||||||
|
},
|
||||||
|
minutes: {
|
||||||
|
'0' => true,
|
||||||
|
'10' => false,
|
||||||
|
'20' => false,
|
||||||
|
'30' => false,
|
||||||
|
'40' => false,
|
||||||
|
'50' => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition: {
|
||||||
|
'ticket.state_id' => { 'operator' => 'is', 'value' => [Ticket::State.lookup(name: 'new').id.to_s, Ticket::State.lookup(name: 'open').id.to_s] },
|
||||||
|
},
|
||||||
|
perform: {
|
||||||
|
'ticket.action' => { 'value' => 'delete' },
|
||||||
|
},
|
||||||
|
disable_notification: true,
|
||||||
|
last_run_at: nil,
|
||||||
|
active: true,
|
||||||
|
created_by_id: 1,
|
||||||
|
created_at: Time.zone.now,
|
||||||
|
updated_by_id: 1,
|
||||||
|
updated_at: Time.zone.now,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_equal('2017-11-11 23:00:00 UTC', job1.next_run_at.to_s)
|
||||||
|
assert_not(job1.last_run_at)
|
||||||
|
|
||||||
|
travel_to Time.zone.local(2017, 11, 16, 22, 0o4, 44)
|
||||||
|
|
||||||
|
Job.run
|
||||||
|
|
||||||
|
job1.reload
|
||||||
|
|
||||||
|
assert_equal('2017-11-18 23:00:00 UTC', job1.next_run_at.to_s)
|
||||||
|
assert_not(job1.last_run_at)
|
||||||
|
|
||||||
|
travel_back
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'execute on certain time' do
|
||||||
|
|
||||||
|
travel_to Time.zone.local(2017, 11, 16, 22, 0o4, 44)
|
||||||
|
|
||||||
|
group1 = Group.lookup(name: 'Users')
|
||||||
|
ticket1 = Ticket.create!(
|
||||||
|
title: 'job test 1',
|
||||||
|
group: group1,
|
||||||
|
customer_id: 2,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
created_by_id: 1,
|
||||||
|
updated_by_id: 1,
|
||||||
|
)
|
||||||
|
ticket2 = Ticket.create!(
|
||||||
|
title: 'job test 2',
|
||||||
|
group: group1,
|
||||||
|
customer_id: 2,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
created_by_id: 1,
|
||||||
|
updated_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
job1 = Job.create_or_update(
|
||||||
|
name: 'Test Job1',
|
||||||
|
timeplan: {
|
||||||
|
days: {
|
||||||
|
Mon: false,
|
||||||
|
Tue: false,
|
||||||
|
Wed: false,
|
||||||
|
Thu: true,
|
||||||
|
Fri: false,
|
||||||
|
Sat: false,
|
||||||
|
Sun: false,
|
||||||
|
},
|
||||||
|
hours: {
|
||||||
|
'0' => false,
|
||||||
|
'1' => false,
|
||||||
|
'2' => false,
|
||||||
|
'3' => false,
|
||||||
|
'4' => false,
|
||||||
|
'5' => false,
|
||||||
|
'6' => false,
|
||||||
|
'7' => false,
|
||||||
|
'8' => false,
|
||||||
|
'9' => false,
|
||||||
|
'10' => false,
|
||||||
|
'11' => false,
|
||||||
|
'12' => false,
|
||||||
|
'13' => false,
|
||||||
|
'14' => false,
|
||||||
|
'15' => false,
|
||||||
|
'16' => false,
|
||||||
|
'17' => false,
|
||||||
|
'18' => false,
|
||||||
|
'19' => false,
|
||||||
|
'20' => false,
|
||||||
|
'21' => false,
|
||||||
|
'22' => false,
|
||||||
|
'23' => true,
|
||||||
|
},
|
||||||
|
minutes: {
|
||||||
|
'0' => true,
|
||||||
|
'10' => false,
|
||||||
|
'20' => false,
|
||||||
|
'30' => false,
|
||||||
|
'40' => false,
|
||||||
|
'50' => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition: {
|
||||||
|
'ticket.state_id' => { 'operator' => 'is', 'value' => [Ticket::State.lookup(name: 'new').id.to_s, Ticket::State.lookup(name: 'open').id.to_s] },
|
||||||
|
},
|
||||||
|
perform: {
|
||||||
|
'ticket.action' => { 'value' => 'delete' },
|
||||||
|
},
|
||||||
|
disable_notification: true,
|
||||||
|
last_run_at: nil,
|
||||||
|
active: true,
|
||||||
|
created_by_id: 1,
|
||||||
|
created_at: Time.zone.now,
|
||||||
|
updated_by_id: 1,
|
||||||
|
updated_at: Time.zone.now,
|
||||||
|
)
|
||||||
|
Job.run
|
||||||
|
|
||||||
|
assert(Ticket.find_by(id: ticket1.id))
|
||||||
|
assert(Ticket.find_by(id: ticket2.id))
|
||||||
|
|
||||||
|
travel_to Time.zone.local(2017, 11, 16, 23, 0o4, 44)
|
||||||
|
|
||||||
|
Job.run
|
||||||
|
|
||||||
|
assert_not(Ticket.find_by(id: ticket1.id))
|
||||||
|
assert_not(Ticket.find_by(id: ticket2.id))
|
||||||
|
|
||||||
|
travel_back
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'delete based on tag' do
|
||||||
|
|
||||||
|
# create ticket
|
||||||
|
group1 = Group.lookup(name: 'Users')
|
||||||
|
group2 = Group.create_or_update(
|
||||||
|
name: 'JobTest2',
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
ticket1 = Ticket.create!(
|
||||||
|
title: 'job test 1',
|
||||||
|
group: group1,
|
||||||
|
customer_id: 2,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
created_at: Time.zone.now - 3.days,
|
||||||
|
updated_at: Time.zone.now - 3.days,
|
||||||
|
created_by_id: 1,
|
||||||
|
updated_by_id: 1,
|
||||||
|
)
|
||||||
|
ticket1.tag_add('spam', 1)
|
||||||
|
ticket1.tag_add('test1 ', 1)
|
||||||
|
ticket2 = Ticket.create!(
|
||||||
|
title: 'job test 2',
|
||||||
|
group: group1,
|
||||||
|
customer_id: 2,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
created_at: Time.zone.now - 1.day,
|
||||||
|
created_by_id: 1,
|
||||||
|
updated_at: Time.zone.now - 1.day,
|
||||||
|
updated_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
job1 = Job.create_or_update(
|
||||||
|
name: 'Test Job1',
|
||||||
|
timeplan: {
|
||||||
|
days: {
|
||||||
|
Mon: true,
|
||||||
|
Tue: true,
|
||||||
|
Wed: true,
|
||||||
|
Thu: true,
|
||||||
|
Fri: true,
|
||||||
|
Sat: true,
|
||||||
|
Sun: true,
|
||||||
|
},
|
||||||
|
hours: {
|
||||||
|
0 => true,
|
||||||
|
1 => true,
|
||||||
|
2 => true,
|
||||||
|
3 => true,
|
||||||
|
4 => true,
|
||||||
|
5 => true,
|
||||||
|
6 => true,
|
||||||
|
7 => true,
|
||||||
|
8 => true,
|
||||||
|
9 => true,
|
||||||
|
10 => true,
|
||||||
|
11 => true,
|
||||||
|
12 => true,
|
||||||
|
13 => true,
|
||||||
|
14 => true,
|
||||||
|
15 => true,
|
||||||
|
16 => true,
|
||||||
|
17 => true,
|
||||||
|
18 => true,
|
||||||
|
19 => true,
|
||||||
|
20 => true,
|
||||||
|
21 => true,
|
||||||
|
22 => true,
|
||||||
|
23 => true,
|
||||||
|
},
|
||||||
|
minutes: {
|
||||||
|
0 => true,
|
||||||
|
10 => true,
|
||||||
|
20 => true,
|
||||||
|
30 => true,
|
||||||
|
40 => true,
|
||||||
|
50 => true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition: {
|
||||||
|
'ticket.tags' => { 'operator' => 'contains one', 'value' => 'spam' },
|
||||||
|
},
|
||||||
|
perform: {
|
||||||
|
'ticket.action' => { 'value' => 'delete' },
|
||||||
|
},
|
||||||
|
disable_notification: true,
|
||||||
|
last_run_at: nil,
|
||||||
|
updated_at: Time.zone.now - 15.minutes,
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(job1.executable?)
|
||||||
|
assert(job1.in_timeplan?)
|
||||||
|
Job.run
|
||||||
|
|
||||||
|
assert_not(Ticket.find_by(id: ticket1.id))
|
||||||
|
assert(Ticket.find_by(id: ticket2.id))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue