2016-11-25 16:10:37 +00:00
|
|
|
# Rails autoload has some issues with same namend sub-classes
|
|
|
|
# in the importer folder require AND simultaniuos requiring
|
|
|
|
# of the same file in different threads so we need to
|
|
|
|
# require them ourself
|
|
|
|
require 'import/otrs/ticket'
|
|
|
|
require 'import/otrs/ticket_factory'
|
|
|
|
require 'import/otrs/article_customer'
|
|
|
|
require 'import/otrs/article_customer_factory'
|
|
|
|
require 'import/otrs/article'
|
|
|
|
require 'import/otrs/article_factory'
|
|
|
|
require 'import/otrs/article/attachment_factory'
|
|
|
|
require 'import/otrs/history'
|
|
|
|
require 'import/otrs/history_factory'
|
|
|
|
require 'import/otrs/history/article'
|
|
|
|
require 'import/otrs/history/move'
|
|
|
|
require 'import/otrs/history/new_ticket'
|
|
|
|
require 'import/otrs/history/priority_update'
|
|
|
|
require 'import/otrs/history/state_update'
|
|
|
|
require 'store'
|
|
|
|
require 'store/object'
|
|
|
|
require 'store/provider/db'
|
|
|
|
require 'store/provider/file'
|
2015-07-21 13:46:01 +00:00
|
|
|
|
2013-02-01 19:58:53 +00:00
|
|
|
module Import
|
2016-11-25 16:10:37 +00:00
|
|
|
module OTRS
|
|
|
|
extend Import::Helper
|
|
|
|
extend Import::OTRS::ImportStats
|
|
|
|
extend Import::OTRS::Async
|
|
|
|
extend Import::OTRS::Diff
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
# rubocop:disable Style/ModuleFunction
|
|
|
|
extend self
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def start
|
|
|
|
log 'Start import...'
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
checks
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
prerequisites
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
base_objects
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
updateable_objects
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
customer_user
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
threaded_import('Ticket')
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
true
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
|
2016-11-28 10:44:56 +00:00
|
|
|
def connection_test
|
|
|
|
Import::OTRS::Requester.connection_test
|
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
private
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def checks
|
|
|
|
check_import_mode
|
2017-03-27 13:22:07 +00:00
|
|
|
check_system_init_done
|
2016-11-28 10:44:56 +00:00
|
|
|
connection_test
|
2014-03-11 09:23:56 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def prerequisites
|
|
|
|
# make sure to create store type otherwise
|
|
|
|
# it might lead to race conditions while
|
|
|
|
# creating it in different import threads
|
|
|
|
Store::Object.create_if_not_exists(name: 'Ticket::Article')
|
2014-03-11 09:23:56 +00:00
|
|
|
end
|
2013-01-07 08:46:38 +00:00
|
|
|
|
2016-11-28 10:44:56 +00:00
|
|
|
def import(remote_object, args = {})
|
2016-11-25 16:10:37 +00:00
|
|
|
log "loading #{remote_object}..."
|
2016-11-28 10:44:56 +00:00
|
|
|
import_action(remote_object, args)
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def threaded_import(remote_object, args = {})
|
|
|
|
thread_count = args[:threads] || 8
|
|
|
|
limit = args[:limit] || 20
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
Thread.abort_on_exception = true
|
|
|
|
threads = {}
|
2017-10-01 12:25:52 +00:00
|
|
|
(1..thread_count).each do |thread|
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2017-10-01 12:25:52 +00:00
|
|
|
threads[thread] = Thread.new do
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2017-03-28 14:23:23 +00:00
|
|
|
# In some environments the Model.reset_column_information
|
|
|
|
# is not reflected to threads. So an import error message appears.
|
|
|
|
# Reset needed model column information for each thread.
|
|
|
|
reset_database_information
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
Thread.current[:thread_no] = thread
|
|
|
|
Thread.current[:loop_count] = 0
|
2013-01-07 08:46:38 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
log "Importing #{remote_object} in steps of #{limit}"
|
|
|
|
loop do
|
|
|
|
# get the offset for the current thread and loop count
|
|
|
|
thread_offset_base = (Thread.current[:thread_no] - 1) * limit
|
|
|
|
thread_step = thread_count * limit
|
|
|
|
offset = Thread.current[:loop_count] * thread_step + thread_offset_base
|
2013-01-07 08:46:38 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
break if !imported?(
|
|
|
|
remote_object: remote_object,
|
|
|
|
limit: limit,
|
|
|
|
offset: offset,
|
|
|
|
diff: args[:diff]
|
|
|
|
)
|
2015-07-24 09:57:45 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
Thread.current[:loop_count] += 1
|
2013-02-17 20:59:57 +00:00
|
|
|
end
|
2016-11-25 16:10:37 +00:00
|
|
|
ActiveRecord::Base.connection.close
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
(1..thread_count).each do |thread|
|
2016-11-25 16:10:37 +00:00
|
|
|
threads[thread].join
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2013-02-17 20:59:57 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def limit_import(remote_object, args = {})
|
|
|
|
offset = 0
|
|
|
|
limit = args[:limit] || 20
|
|
|
|
log "Importing #{remote_object} in steps of #{limit}"
|
|
|
|
loop do
|
2013-02-17 20:59:57 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
break if !imported?(
|
|
|
|
remote_object: remote_object,
|
|
|
|
limit: limit,
|
|
|
|
offset: offset,
|
|
|
|
diff: args[:diff]
|
|
|
|
)
|
2013-02-17 20:59:57 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
offset += limit
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
end
|
2013-01-07 08:46:38 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def imported?(args)
|
|
|
|
log "loading #{args[:limit]} #{args[:remote_object]} starting at #{args[:offset]}..."
|
|
|
|
return false if !import_action(args[:remote_object], limit: args[:limit], offset: args[:offset], diff: args[:diff])
|
|
|
|
true
|
2013-01-07 08:46:38 +00:00
|
|
|
end
|
2016-09-13 08:53:16 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def import_action(remote_object, args = {})
|
|
|
|
records = Import::OTRS::Requester.load(remote_object, limit: args[:limit], offset: args[:offset], diff: args[:diff])
|
2017-11-23 08:09:44 +00:00
|
|
|
if records.blank?
|
2016-11-25 16:10:37 +00:00
|
|
|
log '... no more work.'
|
|
|
|
return false
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
2016-11-25 16:10:37 +00:00
|
|
|
factory_class(remote_object).import(records)
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def factory_class(object)
|
|
|
|
"Import::OTRS::#{object}Factory".constantize
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
# sync settings
|
|
|
|
def base_objects
|
|
|
|
import('SysConfig')
|
|
|
|
import('DynamicField')
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def updateable_objects
|
|
|
|
import('State')
|
|
|
|
import('Priority')
|
|
|
|
import('Queue')
|
|
|
|
import('User')
|
|
|
|
import('Customer')
|
2015-05-07 11:57:19 +00:00
|
|
|
end
|
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
def customer_user
|
|
|
|
limit_import('CustomerUser', limit: 50)
|
|
|
|
end
|
2017-03-28 14:23:23 +00:00
|
|
|
|
|
|
|
def reset_database_information
|
|
|
|
::Ticket.reset_column_information
|
|
|
|
end
|
2016-11-16 10:46:38 +00:00
|
|
|
end
|
2016-11-25 16:22:34 +00:00
|
|
|
end
|