Browse Source

Refactoring: Improve performance by pushing Ticket create screen information on demand to the client instead of checking every X seconds via the Scheduler.

Martin Edenhofer 5 years ago
parent
commit
22911f8616

+ 9 - 6
app/controllers/sessions/collection_ticket.rb

@@ -4,10 +4,6 @@ module ExtraCollection
   def session( collections, assets, user )
 
     # all ticket stuff
-    collections[ Macro.to_app_model ] = []
-    Macro.all.each do |item|
-      assets = item.assets(assets)
-    end
     collections[ Ticket::StateType.to_app_model ] = []
     Ticket::StateType.all.each do |item|
       assets = item.assets(assets)
@@ -30,13 +26,20 @@ module ExtraCollection
     end
     if user.permissions?(['ticket.agent', 'admin.channel_email'])
 
-      # all signatures
+      collections[ Macro.to_app_model ] = []
+      Macro.all.each do |item|
+        assets = item.assets(assets)
+      end
+      collections[ TextModule.to_app_model ] = []
+      TextModule.all.each do |item|
+        assets = item.assets(assets)
+      end
+
       collections[ Signature.to_app_model ] = []
       Signature.all.each do |item|
         assets = item.assets(assets)
       end
 
-      # all email addresses
       collections[ EmailAddress.to_app_model ] = []
       EmailAddress.all.each do |item|
         assets = item.assets(assets)

+ 50 - 0
app/jobs/collection_update_job.rb

@@ -0,0 +1,50 @@
+class CollectionUpdateJob < ApplicationJob
+  include HasActiveJobLock
+
+  def lock_key
+    # "CollectionUpdateJob/:model"
+    "#{self.class.name}/#{arguments[0]}"
+  end
+
+  def perform(model)
+    model = model.safe_constantize
+    return if model.blank?
+
+    assets = {}
+    all = []
+    model.order(id: :asc).find_each do |record|
+      assets = record.assets(assets)
+      all.push record.attributes_with_association_ids
+    end
+
+    return if all.blank?
+
+    Sessions.list.each do |client_id, data|
+      next if client_id.blank?
+
+      user_id = data&.dig(:user, 'id')
+      next if user_id.blank?
+
+      # check permission based access
+      if model.collection_push_permission_value.present?
+        user = User.lookup(id: user_id)
+        next if !user&.permissions?(model.collection_push_permission_value)
+      end
+
+      Rails.logger.debug { "push assets for push_collection #{model} for user #{user_id}" }
+      Sessions.send(client_id, {
+                      data:  assets,
+                      event: 'loadAssets',
+                    })
+
+      Rails.logger.debug { "push push_collection #{model} for user #{user_id}" }
+      Sessions.send(client_id, {
+                      event: 'resetCollection',
+                      data:  {
+                        model.to_app_model => all,
+                      },
+                    })
+    end
+
+  end
+end

+ 29 - 0
app/jobs/ticket_create_screen_job.rb

@@ -0,0 +1,29 @@
+class TicketCreateScreenJob < ApplicationJob
+  include HasActiveJobLock
+
+  def perform
+    Sessions.list.each do |client_id, data|
+      next if client_id.blank?
+
+      user_id = data&.dig(:user, 'id')
+      next if user_id.blank?
+
+      user = User.lookup(id: user_id)
+      next if !user&.permissions?('ticket.agent')
+
+      # get attributes to update
+      ticket_create_attributes = Ticket::ScreenOptions.attributes_to_change(
+        current_user: user,
+      )
+
+      # no data exists
+      next if ticket_create_attributes.blank?
+
+      Rails.logger.error "push ticket_create for user #{user.id}"
+      Sessions.send(client_id, {
+                      event: 'ticket_create_attributes',
+                      data:  ticket_create_attributes,
+                    })
+    end
+  end
+end

+ 34 - 0
app/models/concerns/has_collection_update.rb

@@ -0,0 +1,34 @@
+# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
+module HasCollectionUpdate
+  extend ActiveSupport::Concern
+
+  included do
+    after_commit :push_collection_to_clients
+  end
+
+  # methods defined here are going to extend the class, not the instance of it
+  class_methods do
+
+=begin
+
+define required permissions to push collection to web app
+
+class Model < ApplicationModel
+  include HasCollectionUpdate
+  collection_push_permission('some_permission')
+end
+
+=end
+    attr_accessor :collection_push_permission_value
+
+    def collection_push_permission(*permission)
+      @collection_push_permission_value = permission
+    end
+  end
+
+  def push_collection_to_clients
+    return if Setting.get('import_mode')
+
+    CollectionUpdateJob.set(wait: 10.seconds).perform_later(self.class.name)
+  end
+end

+ 1 - 0
app/models/concerns/has_groups.rb

@@ -250,6 +250,7 @@ module HasGroups
     yield
     self.group_access_buffer = nil
     cache_delete
+    push_ticket_create_screen_background_job
   end
 
   def process_group_access_buffer

+ 17 - 0
app/models/concerns/has_roles.rb

@@ -2,6 +2,14 @@
 module HasRoles
   extend ActiveSupport::Concern
 
+  included do
+    has_and_belongs_to_many :roles,
+                            before_add:    %i[validate_agent_limit_by_role validate_roles],
+                            after_add:     %i[cache_update check_notifications push_ticket_create_screen_for_role_change],
+                            before_remove: :last_admin_check_by_role,
+                            after_remove:  %i[cache_update push_ticket_create_screen_for_role_change]
+  end
+
   # Checks a given Group( ID) for given access(es) for the instance associated roles.
   #
   # @example Group ID param
@@ -36,6 +44,15 @@ module HasRoles
     )
   end
 
+  def push_ticket_create_screen_for_role_change(role)
+    return if Setting.get('import_mode')
+
+    permission = Permission.lookup(name: 'ticket.agent')
+    return if !role.permissions.exists?(id: permission.id)
+
+    push_ticket_create_screen_background_job
+  end
+
   # methods defined here are going to extend the class, not the instance of it
   class_methods do
 

+ 27 - 0
app/models/concerns/has_ticket_create_screen_impact.rb

@@ -0,0 +1,27 @@
+# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
+module HasTicketCreateScreenImpact
+  extend ActiveSupport::Concern
+
+  included do
+    after_commit :push_ticket_create_screen
+  end
+
+  def push_ticket_create_screen?
+    return true if destroyed?
+
+    %w[id name active].any? do |attribute|
+      saved_change_to_attribute?(attribute)
+    end
+  end
+
+  def push_ticket_create_screen
+    return if Setting.get('import_mode')
+    return if !push_ticket_create_screen?
+
+    push_ticket_create_screen_background_job
+  end
+
+  def push_ticket_create_screen_background_job
+    TicketCreateScreenJob.set(wait: 10.seconds).perform_later
+  end
+end

+ 3 - 0
app/models/email_address.rb

@@ -2,6 +2,7 @@
 
 class EmailAddress < ApplicationModel
   include ChecksLatestChangeObserved
+  include HasCollectionUpdate
 
   has_many        :groups,   after_add: :cache_update, after_remove: :cache_update
   belongs_to      :channel, optional: true
@@ -15,6 +16,8 @@ class EmailAddress < ApplicationModel
   after_update    :update_email_address_id
   before_destroy  :delete_group_reference
 
+  collection_push_permission('ticket.agent')
+
 =begin
 
 check and if channel not exists reset configured channels for email addresses

+ 2 - 0
app/models/group.rb

@@ -7,6 +7,8 @@ class Group < ApplicationModel
   include ChecksLatestChangeObserved
   include HasHistory
   include HasObjectManagerAttributesValidation
+  include HasCollectionUpdate
+  include HasTicketCreateScreenImpact
 
   belongs_to :email_address, optional: true
   belongs_to :signature, optional: true

+ 3 - 0
app/models/macro.rb

@@ -4,10 +4,13 @@ class Macro < ApplicationModel
   include ChecksClientNotification
   include ChecksLatestChangeObserved
   include CanSeed
+  include HasCollectionUpdate
 
   store     :perform
   validates :name, presence: true
   validates :ux_flow_next_up, inclusion: { in: %w[none next_task next_from_overview] }
 
   has_and_belongs_to_many :groups, after_add: :cache_update, after_remove: :cache_update, class_name: 'Group'
+
+  collection_push_permission('ticket.agent')
 end

Some files were not shown because too many files changed in this diff