2021-06-01 12:20:20 +00:00
|
|
|
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
|
|
|
|
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
|
|
|
|
extend self
|
2015-05-07 11:57:19 +00:00
|
|
|
|
2020-10-22 13:38:34 +00:00
|
|
|
# Start import with specific parameters.
|
|
|
|
# Useful for debug and continuing from breakpoint of last not success import
|
|
|
|
#
|
|
|
|
# @example
|
|
|
|
# Import::OTRS::start() - Nomrmal usage
|
|
|
|
#
|
|
|
|
# Import::OTRS::start(thread: 1, offset: 1000) - Run the task in Single-Thread and start from offset 1000
|
|
|
|
|
|
|
|
def start(args = {})
|
2016-11-25 16:10:37 +00:00
|
|
|
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
|
|
|
|
2020-10-22 13:38:34 +00:00
|
|
|
threaded_import('Ticket', args)
|
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 = {})
|
2020-10-22 13:38:34 +00:00
|
|
|
thread_count = args[:threads] || 8
|
|
|
|
limit = args[:limit] || 20
|
|
|
|
start_offset_base = args[:offset] || 0
|
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
|
2020-10-22 13:38:34 +00:00
|
|
|
offset = Thread.current[:loop_count] * thread_step + thread_offset_base + start_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
|
2020-09-30 09:07:01 +00:00
|
|
|
(1..thread_count).each do |thread| # rubocop:disable Style/CombinableLoops
|
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])
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2016-11-25 16:10:37 +00:00
|
|
|
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
|