Skip to content

Commit

Permalink
Performance: Observing every Overview of each Agent Session doesn't s…
Browse files Browse the repository at this point in the history
…cale well on larger systems (60 Overviews per Agent). With this change only the last 5 used Overviews are checked on every iteration. A full check is still performed ever 60 seconds. This reduces the overall load.
  • Loading branch information
zammad-sync authored and thorsteneckel committed Nov 28, 2019
1 parent f41aa09 commit 4e8cf20
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 48 deletions.
6 changes: 6 additions & 0 deletions app/assets/javascripts/app/controllers/ticket_overview.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,10 @@ class Navbar extends App.Controller
if item.link is @view
@title item.name, true

# send first view info
if !@view && data && data[0] && data[0].link
App.WebSocket.send(event:'ticket_overview_select', data: { view: data[0].link })

# redirect to first view
if @activeState && !@view && !@vertical
view = data[0].link
Expand Down Expand Up @@ -1037,6 +1041,8 @@ class Table extends App.Controller
@view_mode = App.LocalStorage.get("mode:#{@view}", @Session.get('id')) || 's'
console.log 'notice', 'view:', @view, @view_mode

App.WebSocket.send(event:'ticket_overview_select', data: { view: @view })

# get ticket list
ticketListShow = []
for ticket in tickets
Expand Down
6 changes: 5 additions & 1 deletion app/assets/javascripts/app/controllers/ticket_zoom.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,10 @@ class App.TicketZoom extends App.Controller
if macro && macro.ux_flow_next_up
taskAction = macro.ux_flow_next_up

nextTicket = undefined
if taskAction is 'closeNextInOverview' || taskAction is 'next_from_overview'
nextTicket = @getNextTicketInOverview()

# submit changes
@ajax(
id: "ticket_update_#{ticket.id}"
Expand All @@ -916,8 +920,8 @@ class App.TicketZoom extends App.Controller
@sidebarWidget.commit()

if taskAction is 'closeNextInOverview' || taskAction is 'next_from_overview'
@openTicketInOverview(nextTicket)
App.Event.trigger('overview:fetch')
@taskOpenNextTicketInOverview()
return

if taskAction is 'closeTab' || taskAction is 'next_task'
Expand Down
24 changes: 21 additions & 3 deletions app/assets/javascripts/app/lib/mixins/ticket_navigable.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,40 @@ App.TicketNavigable =
show: true
)

getNextTicketInOverview: ->
return if !@ticket
return if !@overview_id

App.Overview.find(@overview_id).nextTicket(@ticket)

openTicketInOverview: (nextTicket) ->
if nextTicket
@taskCloseTicket()
@taskLoadTicket(nextTicket.id)
return

@taskCloseTicket(true)

taskOpenNextTicketInOverview: ->
if !(@overview_id? && @ticket?)
@taskCloseTicket(true)
return
next_ticket = App.Overview.find(@overview_id).nextTicket(@ticket)
if next_ticket

nextTicket = @getNextTicketInOverview()
if nextTicket
@taskCloseTicket()
@taskLoadTicket(next_ticket.id)
@taskLoadTicket(nextTicket.id)
return

@taskCloseTicket(true)

taskCloseTicket: (openNext = false) ->
App.TaskManager.remove(@taskKey)
return if !openNext

nextTaskUrl = App.TaskManager.nextTaskUrl()
if nextTaskUrl
@navigate nextTaskUrl
return

@navigate '#'
22 changes: 20 additions & 2 deletions app/models/ticket/overviews.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ module Ticket::Overviews
result = Ticket::Overviews.all(current_user: User.find(3))
certain overviews by user
result = Ticket::Overviews.all(current_user: User.find(3), links: ['all_unassigned', 'my_assigned'])
returns
result = [overview1, overview2]
Expand All @@ -15,6 +19,7 @@ module Ticket::Overviews

def self.all(data)
current_user = data[:current_user]
links = data[:links]

# get customer overviews
role_ids = User.joins(:roles).where(users: { id: current_user.id, active: true }, roles: { active: true }).pluck('roles.id')
Expand All @@ -23,6 +28,9 @@ def self.all(data)
if current_user.organization_id && current_user.organization.shared
overview_filter.delete(:organization_shared)
end
if links.present?
overview_filter[:link] = links
end
overviews = Overview.joins(:roles).left_joins(:users).where(overviews_roles: { role_id: role_ids }, overviews_users: { user_id: nil }, overviews: overview_filter).or(Overview.joins(:roles).left_joins(:users).where(overviews_roles: { role_id: role_ids }, overviews_users: { user_id: current_user.id }, overviews: overview_filter)).distinct('overview.id').order(:prio, :name)
return overviews
end
Expand All @@ -35,12 +43,21 @@ def self.all(data)
if User.where('out_of_office = ? AND out_of_office_start_at <= ? AND out_of_office_end_at >= ? AND out_of_office_replacement_id = ? AND active = ?', true, Time.zone.today, Time.zone.today, current_user.id, true).count.positive?
overview_filter_not = {}
end
if links.present?
overview_filter[:link] = links
end
Overview.joins(:roles).left_joins(:users).where(overviews_roles: { role_id: role_ids }, overviews_users: { user_id: nil }, overviews: overview_filter).or(Overview.joins(:roles).left_joins(:users).where(overviews_roles: { role_id: role_ids }, overviews_users: { user_id: current_user.id }, overviews: overview_filter)).where.not(overview_filter_not).distinct('overview.id').order(:prio, :name)
end

=begin
result = Ticket::Overviews.index(User.find(123))
index of all overviews by user
result = Ticket::Overviews.index(User.find(3))
index of certain overviews by user
result = Ticket::Overviews.index(User.find(3), ['all_unassigned', 'my_assigned'])
returns
Expand Down Expand Up @@ -75,9 +92,10 @@ def self.all(data)
=end

def self.index(user)
def self.index(user, links = nil)
overviews = Ticket::Overviews.all(
current_user: user,
links: links,
)
return [] if overviews.blank?

Expand Down
22 changes: 9 additions & 13 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,17 @@
# Show full error reports.
config.consider_all_requests_local = true

# Commented out to ensure using file cache store as described in config/application.rb
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
# if Rails.root.join('tmp', 'caching-dev.txt').exist?
# config.action_controller.perform_caching = true
#
# config.cache_store = :memory_store
# config.public_file_server.headers = {
# 'Cache-Control' => "public, max-age=#{2.days.to_i}"
# }
# else
# config.action_controller.perform_caching = false
#
# config.cache_store = :null_store
# end
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true

config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
end

# Store uploaded files on the local file system (see config/storage.yml for options)
# config.active_storage.service = :local
Expand Down
97 changes: 84 additions & 13 deletions lib/sessions/backend/ticket_overview_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,95 @@ def self.reset(user_id)
Cache.write("TicketOverviewPull::#{user_id}", { needed: true })
end

def initialize(user, asset_lookup, client = nil, client_id = nil, ttl = 8)
def initialize(user, asset_lookup, client = nil, client_id = nil, ttl = 7)
@user = user
@client = client
@client_id = client_id
@ttl = ttl
@asset_lookup = asset_lookup
@last_change = nil
@last_index_lists = nil
@last_overview = {}
@last_overview_change = nil
@last_ticket_change = nil
@last_full_fetch = nil
end

def self.overview_history_append(overview, user_id)
key = "TicketOverviewHistory::#{user_id}"
history = Cache.get(key) || []

history.prepend overview
history.uniq!
if history.count > 4
history.pop
end

Cache.write(key, history)
end

def self.overview_history_get(user_id)
Cache.get("TicketOverviewHistory::#{user_id}")
end

def load

# get whole collection
index_and_lists = Ticket::Overviews.index(@user)
index_and_lists = nil
local_overview_changed = overview_changed?
if !@last_index_lists || !@last_full_fetch || @last_full_fetch < (Time.zone.now.to_i - 60) || local_overview_changed

# check if min one ticket has changed
return if !ticket_changed?(true) && !local_overview_changed

index_and_lists = Ticket::Overviews.index(@user)
@last_full_fetch = Time.zone.now.to_i
else

# check if min one ticket has changed
return if !ticket_changed? && !local_overview_changed

index_and_lists_local = Ticket::Overviews.index(@user, Sessions::Backend::TicketOverviewList.overview_history_get(@user.id))

# compare index_and_lists_local to index_and_lists_local
# return if no changes

index_and_lists = []
@last_index_lists.each do |last_index|
found_in_particular_index = false
index_and_lists_local.each do |local_index|
next if local_index[:overview][:id] != last_index[:overview][:id]

index_and_lists.push local_index
found_in_particular_index = true
break
end
next if found_in_particular_index == true

index_and_lists.push last_index
end
end

# no data exists
return if index_and_lists.blank?

# no change exists
return if @last_change == index_and_lists
return if @last_index_lists == index_and_lists

# remember last state
@last_change = index_and_lists
@last_index_lists = index_and_lists

index_and_lists
end

def local_to_run?
return false if !@time_now

return true if pull_overview?

false
end

def pull_overview?
result = Cache.get("TicketOverviewPull::#{@user.id}")
Cache.delete("TicketOverviewPull::#{@user.id}") if result
return true if result
Expand All @@ -48,14 +105,6 @@ def push

@time_now = Time.zone.now.to_i

# check if min one ticket or overview has changed
last_overview_change = Overview.latest_change
last_ticket_change = Ticket.latest_change
return if last_ticket_change == @last_ticket_change && last_overview_change == @last_overview_change

@last_overview_change = last_overview_change
@last_ticket_change = last_ticket_change

# load current data
index_and_lists = load
return if !index_and_lists
Expand Down Expand Up @@ -134,4 +183,26 @@ def push
nil
end

def overview_changed?

# check if min one overview has changed
last_overview_change = Overview.latest_change
return false if last_overview_change == @last_overview_change

@last_overview_change = last_overview_change

true
end

def ticket_changed?(reset = false)

# check if min one ticket has changed
last_ticket_change = Ticket.latest_change
return false if last_ticket_change == @last_ticket_change

@last_ticket_change = last_ticket_change if reset

true
end

end
23 changes: 23 additions & 0 deletions lib/sessions/event/ticket_overview_select.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Sessions::Event::TicketOverviewSelect < Sessions::Event::Base

=begin
Event module to serve spool messages and send them to new client connection.
To execute this manually, just paste the following into the browser console
App.WebSocket.send({event:'spool'})
=end

def run
return if @payload['data'].blank?
return if @payload['data']['view'].blank?
return if @session['id'].blank?

Sessions::Backend::TicketOverviewList.overview_history_append(@payload['data']['view'], @session['id'])

nil
end

end
Loading

0 comments on commit 4e8cf20

Please sign in to comment.