Class: Flydata::Command::Sync
- Inherits:
-
Base
- Object
- Base
- Flydata::Command::Sync
show all
- Includes:
- Helpers
- Defined in:
- lib/flydata/command/sync.rb
Defined Under Namespace
Classes: SyncDataEntryError
Constant Summary
collapse
- INSERT_PROGRESS_INTERVAL =
1000
- SERVER_DATA_PROCESSING_TIMEOUT =
600
- STATUS_PARSING =
'PARSING'
- STATUS_WAITING =
'WAITING'
- STATUS_COMPLETE =
'COMPLETE'
Constants included
from Helpers
Helpers::UNIT_PREFIX
Instance Attribute Summary collapse
Attributes inherited from Base
#opts
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Helpers
as_size, development?, env_mode, env_suffix, flydata_api_host_file, flydata_conf_file, flydata_version, format_menu_list, parse_command, retry_on, to_command_class, usage_text
Methods inherited from Base
#ask_input_table_name, #ask_yes_no, #choose_one, #flydata, #initialize, #newline, #register_crontab, #retrieve_data_entries, #separator
#before_logging, #log_error_stderr, #log_info_stdout, #log_warn_stderr
Instance Attribute Details
#ddl_tables ⇒ Object
Returns the value of attribute ddl_tables.
27
28
29
|
# File 'lib/flydata/command/sync.rb', line 27
def ddl_tables
@ddl_tables
end
|
#initial_sync(tables, de = nil) ⇒ Object
Returns the value of attribute initial_sync.
27
28
29
|
# File 'lib/flydata/command/sync.rb', line 27
def initial_sync
@initial_sync
end
|
#new_tables ⇒ Object
Returns the value of attribute new_tables.
27
28
29
|
# File 'lib/flydata/command/sync.rb', line 27
def new_tables
@new_tables
end
|
Class Method Details
.slop ⇒ Object
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/flydata/command/sync.rb', line 32
def self.slop
Slop.new do
on 'c', 'skip-cleanup', 'Skip server cleanup'
on 'f', 'skip-flush', 'Skip server flush'
on 'y', 'yes', 'Skip command prompt assuming yes to all questions. Use this for batch operation.'
on 'd', 'dump-file', 'Dump mysqldump into a file. Use this for debugging after making sure the free space.' on 's', 'dump-stream', 'Dump mysqldump stream instead of saving dump file. It might cause timeout error if db size is larger than 10GB.'
on 'n', 'no-flydata-start', 'Don\'t start the flydata agent after initial sync.'
on 'ff', 'Skip checking query queue and flush'
end
end
|
.slop_flush ⇒ Object
128
129
130
131
132
133
|
# File 'lib/flydata/command/sync.rb', line 128
def self.slop_flush
Slop.new do
on 'f', 'skip-flush', 'Skip server flush'
on 'y', 'yes', 'Skip command prompt assuming yes to all questions. Use this for batch operation.'
end
end
|
.slop_generate_table_ddl ⇒ Object
280
281
282
283
284
285
286
287
|
# File 'lib/flydata/command/sync.rb', line 280
def self.slop_generate_table_ddl
Slop.new do
on 'c', 'ctl-only', 'Only generate FlyData Control definitions'
on 'y', 'yes', 'Skip command prompt assuming yes to all questions. Use this for batch operation.'
on 's', 'skip-primary-key-check', 'Skip primary key check when generating DDL'
on 'all-tables', 'Generate all table schema'
end
end
|
.slop_reset ⇒ Object
150
151
152
153
154
155
|
# File 'lib/flydata/command/sync.rb', line 150
def self.slop_reset
Slop.new do
on 'c', 'client', 'Resets client only.'
on 'y', 'yes', 'Skip command prompt assuming yes to all questions. Use this for batch operation.'
end
end
|
Instance Method Details
#check ⇒ Object
256
257
258
259
260
261
262
263
264
265
266
|
# File 'lib/flydata/command/sync.rb', line 256
def check
de = retrieve_sync_data_entry
retry_on(RestClient::Exception) do
status = do_check(de)
if status['complete']
nil
else
status
end
end
end
|
#flush ⇒ Object
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
# File 'lib/flydata/command/sync.rb', line 135
def flush
begin
flush_buffer_and_stop
rescue ServerDataProcessingTimeout => e
ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
ee.description = <<EOS
Data processing is taking more than expected. Please contact [email protected] to check the system status.
EOS
ee.set_backtrace e.backtrace
raise ee
end
log_info_stdout("Buffers have been flushed and the sender process has been stopped.")
end
|
#generate_table_ddl(*tables) ⇒ Object
289
290
291
292
293
294
|
# File 'lib/flydata/command/sync.rb', line 289
def generate_table_ddl(*tables)
de = retrieve_sync_data_entry
dp = flydata.data_port.get
Flydata::MysqlCompatibilityCheck.new(dp, de['mysql_data_entry_preference']).check
do_generate_table_ddl(de, tables)
end
|
#handle_mysql_sync(tables = nil) ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
# File 'lib/flydata/command/sync.rb', line 78
def handle_mysql_sync(tables=nil)
de = retrieve_sync_data_entry
set_current_tables(de)
verify_input_tables(tables, de['mysql_data_entry_preference']['tables'])
unless @new_tables.empty?
say("We've noticed that these tables have not been synced yet: #{@new_tables.join(", ")}")
unless @ddl_tables.empty?
say(" WARNING: We've noticed that at least one of these tables have not had their DDL generated yet.")
say(" We recommend you run our 'flydata sync:generate_table_ddl > create_table.sql'")
say(" to generate SQL to run on Redshift to create the correct tables")
say(" Without running this sql on your Redshift cluster, there may be issues with your data")
end
if ask_yes_no("Do you want to run initial sync on all of these tables now?")
tables = @initial_sync ? [] : @new_tables
initial_sync(tables, de)
else
unless @ddl_tables.empty?
say(" You can generate DDL SQL for your new tables by running this command")
say(" $> flydata sync:generate_table_ddl > create_table.sql")
end
puts "Without syncing these tables, we cannot start the flydata process"
raise "Please try again"
end
end
end
|
#reset(*tables) ⇒ Object
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
# File 'lib/flydata/command/sync.rb', line 157
def reset(*tables)
msg = tables.empty? ? '' : " for these tables : #{tables.join(" ")}"
return unless ask_yes_no("This resets the current sync#{msg}. Are you sure?")
sender = Flydata::Command::Sender.new
sender.flush_client_buffer sender.stop
de = retrieve_sync_data_entry
all_tables = de['mysql_data_entry_preference']['tables']
verify_input_tables(tables, all_tables)
begin
wait_for_server_buffer(SERVER_DATA_PROCESSING_TIMEOUT)
rescue ServerDataProcessingTimeout => e
ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
ee.description = <<EOS
Data processing is taking more than expected. Please contact [email protected] to check the system status.
Once checked, you can continue sync reset with the following command
flydata sync:reset #{tables.empty? ? '' : tables.join(" ")}
EOS
ee.set_backtrace e.backtrace
raise ee
end
cleanup_sync_server(de, tables) unless opts.client?
sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
delete_files = [
sync_fm.dump_file_path,
sync_fm.dump_pos_path,
sync_fm.mysql_table_marshal_dump_path,
sync_fm.sync_info_file,
sync_fm.table_position_file_paths(*tables),
sync_fm.table_binlog_pos_paths(*tables),
sync_fm.table_binlog_pos_init_paths(*tables),
sync_fm.table_rev_file_paths(*tables),
sync_fm.table_ddl_file_paths(*tables)
]
delete_files << sync_fm.binlog_path if tables.empty? or all_tables.empty?
delete_files.flatten.each do |path|
FileUtils.rm(path) if File.exists?(path)
end
sync_fm.close
log_info_stdout("Reset completed successfully.")
end
|
#run(*tables) ⇒ Object
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# File 'lib/flydata/command/sync.rb', line 45
def run(*tables)
sender = Flydata::Command::Sender.new
if (sender.process_exist?)
if tables.empty?
log_warn_stderr("FlyData Agent is already running. If you'd like to restart FlyData Sync from scratch, run 'flydata sync:reset' first.")
else
log_warn_stderr("Flydata Agent is already running. If you'd like to Sync the table(s), run 'flydata sync:flush' first.")
end
exit 1
end
handle_mysql_sync(tables)
unless opts.no_flydata_start?
log_info_stdout("Starting FlyData Agent...")
Flydata::Command::Sender.new.start(quiet: true)
log_info_stdout(" -> Done")
end
dashboard_url = "#{flydata.flydata_api_host}/dashboard"
redshift_console_url = "#{flydata.flydata_api_host}/redshift_clusters/query/new"
last_message = ALL_DONE_MESSAGE_TEMPLATE % [redshift_console_url, dashboard_url]
log_info_stdout(last_message)
end
|
#skip ⇒ Object
269
270
271
272
273
274
275
276
277
278
|
# File 'lib/flydata/command/sync.rb', line 269
def skip
de = retrieve_sync_data_entry
sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
binlog_path = sync_fm.binlog_path
sync_fm.close
`touch #{binlog_path}`
log_info_stdout("Created an empty binlog position file.")
log_info_stdout("-> #{binlog_path}")
log_info_stdout("Run 'flydata start' to start continuous sync.")
end
|
#try_mysql_sync ⇒ Object
72
73
74
75
76
|
# File 'lib/flydata/command/sync.rb', line 72
def try_mysql_sync
handle_mysql_sync()
rescue SyncDataEntryError
return
end
|
#wait_for_server_buffer(timeout = 0) ⇒ Object
203
204
205
206
207
208
209
210
211
212
213
214
215
|
# File 'lib/flydata/command/sync.rb', line 203
def wait_for_server_buffer(timeout = 0)
start_time = Time.now
log_info_stdout("Waiting for the server buffer to get empty.")
prev_message =nil
while (status = check) && (status['state'] == 'processing')
prev_message = status['message']
if timeout > 0 && Time.now - start_time > timeout
raise ServerDataProcessingTimeout.new
end
print_progress(status)
sleep 10
end
end
|
#wait_for_server_data_processing(timeout = 0) ⇒ Object
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
|
# File 'lib/flydata/command/sync.rb', line 217
def wait_for_server_data_processing(timeout = 0)
state = :PROCESS
start_time = Time.now
log_info_stdout("Uploading data to Redshift...")
sleep 10
status = nil
prev_message =nil
while (status = check)
if state == :PROCESS && status['state'] == 'uploading'
log_info_stdout(" -> Done")
state = :UPLOAD
log_info_stdout("Finishing data upload...")
end
if state == :UPLOAD && opts.ff?
log_info_stdout("Skip checking for pending uploads")
break
end
if status['message'] != prev_message
start_time = Time.now
end
prev_message = status['message']
if timeout > 0 && Time.now - start_time > timeout
raise ServerDataProcessingTimeout.new
end
print_progress(status)
sleep 10
end
if (state == :PROCESS)
log_info_stdout(" -> Done")
log_info_stdout("Finishing data upload...")
end
log_info_stdout(" -> Done")
end
|