otrs.rb 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. # Rails autoload has some issues with same namend sub-classes
  2. # in the importer folder require AND simultaniuos requiring
  3. # of the same file in different threads so we need to
  4. # require them ourself
  5. require_dependency 'import/otrs/ticket'
  6. require_dependency 'import/otrs/ticket_factory'
  7. require_dependency 'import/otrs/article_customer'
  8. require_dependency 'import/otrs/article_customer_factory'
  9. require_dependency 'import/otrs/article'
  10. require_dependency 'import/otrs/article_factory'
  11. require_dependency 'import/otrs/article/attachment_factory'
  12. require_dependency 'import/otrs/history'
  13. require_dependency 'import/otrs/history_factory'
  14. require_dependency 'import/otrs/history/article'
  15. require_dependency 'import/otrs/history/move'
  16. require_dependency 'import/otrs/history/new_ticket'
  17. require_dependency 'import/otrs/history/priority_update'
  18. require_dependency 'import/otrs/history/state_update'
  19. require_dependency 'store'
  20. require_dependency 'store/object'
  21. require_dependency 'store/provider/db'
  22. require_dependency 'store/provider/file'
  23. module Import
  24. module OTRS
  25. extend Import::Helper
  26. extend Import::OTRS::ImportStats
  27. extend Import::OTRS::Async
  28. extend Import::OTRS::Diff
  29. extend self
  30. # Start import with specific parameters.
  31. # Useful for debug and continuing from breakpoint of last not success import
  32. #
  33. # @example
  34. # Import::OTRS::start() - Nomrmal usage
  35. #
  36. # Import::OTRS::start(thread: 1, offset: 1000) - Run the task in Single-Thread and start from offset 1000
  37. def start(args = {})
  38. log 'Start import...'
  39. checks
  40. prerequisites
  41. base_objects
  42. updateable_objects
  43. customer_user
  44. threaded_import('Ticket', args)
  45. true
  46. end
  47. def connection_test
  48. Import::OTRS::Requester.connection_test
  49. end
  50. private
  51. def checks
  52. check_import_mode
  53. check_system_init_done
  54. connection_test
  55. end
  56. def prerequisites
  57. # make sure to create store type otherwise
  58. # it might lead to race conditions while
  59. # creating it in different import threads
  60. Store::Object.create_if_not_exists(name: 'Ticket::Article')
  61. end
  62. def import(remote_object, args = {})
  63. log "loading #{remote_object}..."
  64. import_action(remote_object, args)
  65. end
  66. def threaded_import(remote_object, args = {})
  67. thread_count = args[:threads] || 8
  68. limit = args[:limit] || 20
  69. start_offset_base = args[:offset] || 0
  70. Thread.abort_on_exception = true
  71. threads = {}
  72. (1..thread_count).each do |thread|
  73. threads[thread] = Thread.new do
  74. # In some environments the Model.reset_column_information
  75. # is not reflected to threads. So an import error message appears.
  76. # Reset needed model column information for each thread.
  77. reset_database_information
  78. Thread.current[:thread_no] = thread
  79. Thread.current[:loop_count] = 0
  80. log "Importing #{remote_object} in steps of #{limit}"
  81. loop do
  82. # get the offset for the current thread and loop count
  83. thread_offset_base = (Thread.current[:thread_no] - 1) * limit
  84. thread_step = thread_count * limit
  85. offset = Thread.current[:loop_count] * thread_step + thread_offset_base + start_offset_base
  86. break if !imported?(
  87. remote_object: remote_object,
  88. limit: limit,
  89. offset: offset,
  90. diff: args[:diff]
  91. )
  92. Thread.current[:loop_count] += 1
  93. end
  94. ActiveRecord::Base.connection.close
  95. end
  96. end
  97. (1..thread_count).each do |thread| # rubocop:disable Style/CombinableLoops
  98. threads[thread].join
  99. end
  100. end
  101. def limit_import(remote_object, args = {})
  102. offset = 0
  103. limit = args[:limit] || 20
  104. log "Importing #{remote_object} in steps of #{limit}"
  105. loop do
  106. break if !imported?(
  107. remote_object: remote_object,
  108. limit: limit,
  109. offset: offset,
  110. diff: args[:diff]
  111. )
  112. offset += limit
  113. end
  114. end
  115. def imported?(args)
  116. log "loading #{args[:limit]} #{args[:remote_object]} starting at #{args[:offset]}..."
  117. return false if !import_action(args[:remote_object], limit: args[:limit], offset: args[:offset], diff: args[:diff])
  118. true
  119. end
  120. def import_action(remote_object, args = {})
  121. records = Import::OTRS::Requester.load(remote_object, limit: args[:limit], offset: args[:offset], diff: args[:diff])
  122. if records.blank?
  123. log '... no more work.'
  124. return false
  125. end
  126. factory_class(remote_object).import(records)
  127. end
  128. def factory_class(object)
  129. "Import::OTRS::#{object}Factory".constantize
  130. end
  131. # sync settings
  132. def base_objects
  133. import('SysConfig')
  134. import('DynamicField')
  135. end
  136. def updateable_objects
  137. import('State')
  138. import('Priority')
  139. import('Queue')
  140. import('User')
  141. import('Customer')
  142. end
  143. def customer_user
  144. limit_import('CustomerUser', limit: 50)
  145. end
  146. def reset_database_information
  147. ::Ticket.reset_column_information
  148. end
  149. end
  150. end