Class: Flydata::Output::TcpForwarder

Inherits:
Object
  • Object
show all
Defined in:
lib/flydata/command/sync.rb

Direct Known Subclasses

SslForwarder

Constant Summary collapse

FORWARD_HEADER =
[0x92].pack('C')
BUFFER_SIZE =

32M

1024 * 1024 * 32
DEFUALT_SEND_TIMEOUT =

1 minute

60
RETRY_INTERVAL =
2
RETRY_LIMIT =
10

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tag, servers, options = {}) ⇒ TcpForwarder

Returns a new instance of TcpForwarder.



396
397
398
399
400
401
402
403
404
405
# File 'lib/flydata/command/sync.rb', line 396

def initialize(tag, servers, options = {})
  @tag = tag
  unless servers and servers.kind_of?(Array) and not servers.empty?
    raise "Servers must not be empty."
  end
  @servers = servers
  @server_index = 0
  set_options(options)
  reset
end

Instance Attribute Details

#buffer_record_count ⇒ Object (readonly)

Returns the value of attribute buffer_record_count.



415
416
417
# File 'lib/flydata/command/sync.rb', line 415

def buffer_record_count
  @buffer_record_count
end

#buffer_size ⇒ Object (readonly)

Returns the value of attribute buffer_size.



415
416
417
# File 'lib/flydata/command/sync.rb', line 415

def buffer_size
  @buffer_size
end

Instance Method Details

#close ⇒ Object



510
511
512
# File 'lib/flydata/command/sync.rb', line 510

def close
  flush
end

#connect(server) ⇒ Object



487
488
489
490
491
492
493
494
495
496
497
498
# File 'lib/flydata/command/sync.rb', line 487

def connect(server)
  host, port = server.split(':')
  sock = TCPSocket.new(host, port.to_i)

  # Set options
  opt = [1, DEFUALT_SEND_TIMEOUT].pack('I!I!')
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
  opt = [DEFUALT_SEND_TIMEOUT, 0].pack('L!L!')
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, opt)

  sock
end

#emit(records, time = Time.now.to_i) ⇒ Object



417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/flydata/command/sync.rb', line 417

def emit(records, time = Time.now.to_i)
  records = [records] unless records.kind_of?(Array)
  records.each do |record|
    event_data = [time,record].to_msgpack
    @buffer_records << event_data
    @buffer_record_count += 1
    @buffer_size += event_data.bytesize
  end
  if @buffer_size > @buffer_size_limit
    send
  else
    false
  end
end

#flush ⇒ Object



506
507
508
# File 'lib/flydata/command/sync.rb', line 506

def flush
  send
end

#pickup_server ⇒ Object

TODO: Check server status



478
479
480
481
482
483
484
485
# File 'lib/flydata/command/sync.rb', line 478

def pickup_server
  ret_server = @servers[@server_index]
  @server_index += 1
  if @server_index >= (@servers.count)
    @server_index = 0
  end
  ret_server
end

#reset ⇒ Object



500
501
502
503
504
# File 'lib/flydata/command/sync.rb', line 500

def reset
  @buffer_records = ''
  @buffer_record_count = 0
  @buffer_size = 0
end

#send ⇒ Object

TODO retry logic



433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# File 'lib/flydata/command/sync.rb', line 433

def send
  if @buffer_size > 0
    puts "  -> Sending #{@buffer_record_count}records #{@buffer_size}byte"
  else
    return false
  end
  if ENV['FLYDATA_BENCHMARK']
    reset
    return true
  end
  sock = nil
  retry_count = 0
  begin
    sock = connect(pickup_server)

    # Write header
    sock.write FORWARD_HEADER
    # Write tag
    sock.write @tag.to_msgpack
    # Write records
    sock.write [0xdb, @buffer_records.bytesize].pack('CN')
    StringIO.open(@buffer_records) do |i|
      FileUtils.copy_stream(i, sock)
    end
  rescue => e
    retry_count += 1
    if retry_count > RETRY_LIMIT
      puts "! Error: Failed to send data. Exceeded the retry limit. retry_count:#{retry_count}"
      raise e
    end
    puts "! Warn: Retring to send data. retry_count:#{retry_count} error=#{e.to_s}"
    wait_time = RETRY_INTERVAL ** retry_count
    puts "  Now waiting for next retry. time=#{wait_time}sec"
    sleep wait_time
    retry
  ensure
    if sock
      sock.close rescue nil
    end
  end
  reset
  true
end

#set_options(options) ⇒ Object



407
408
409
410
411
412
413
# File 'lib/flydata/command/sync.rb', line 407

def set_options(options)
  if options[:buffer_size_limit]
    @buffer_size_limit = options[:buffer_size_limit]
  else
    @buffer_size_limit = BUFFER_SIZE
  end
end