tzispa_data 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01f0dadd4b7adc9d99c80f8f394ba1524be42acf
4
- data.tar.gz: b3faf8c93ce0ffa0ba43d3e9c43e2d2bfc986079
3
+ metadata.gz: a9234402ed79a266e628d427704877a3e1a7286a
4
+ data.tar.gz: 52cde789079f0e62cddb344ebb1b7c612316156f
5
5
  SHA512:
6
- metadata.gz: d88c26dcb9256d4ad41f8c06249e9b0d0f3ad9c673c0060d9542bd57ae7eb44053cf7a6a04ecc1bfbb163ca70763f1c9e39615d0ad643173751027d87d3e16fe
7
- data.tar.gz: 1493679c1e6cec07fb809e09548092696a9182bb99602671f3ae05667ea88c68f886c4f8cf8811416b8c2eef79637726f3180040f80a197db4c08e3a6bb889df
6
+ metadata.gz: 72bc1e0dd2b08fa542e3e758b3c6465da6b8c9b6017e82e114c9fb684b221e0876a595e4085541fdfc415c28952b70ab4b86a0b6ef91134f7881f6655c6271a6
7
+ data.tar.gz: 355d77a38353fe5af31d77927d3dff04f22e89337e6a3b105bc4dc94279b383dc1c134e1ef8a844dd97985bd5aecda3efc12e464af4ece17b2755a18c1589275
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  Tzispa Data
2
2
 
3
+ ## v0.2.0
4
+ - add data transporter class for import/export data
5
+
3
6
  ## v0.1.4
4
7
  - add connection validation config in adapters
5
8
 
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzispa
4
+ module Data
5
+
6
+ class Transporter
7
+
8
+ DEFAULT_ENCODING = 'ASCII-8BIT'
9
+ DEFAULT_BUFFER_SIZE = 2048
10
+ DEFAULT_LINE_SEPARATOR = "\n"
11
+
12
+ attr_reader :filename, :buffer_size, :encoding, :line_separator, :data_separator, :line_size, :strip, :check_count, :lines, :errors
13
+
14
+ def initialize(fn, options = {})
15
+ @filename = fn
16
+ @buffer_size = options[:buffer_size] || DEFAULT_BUFFER_SIZE
17
+ @encoding = options[:encoding] || DEFAULT_ENCODING
18
+ @line_separator = options[:line_separator] || DEFAULT_LINE_SEPARATOR
19
+ @line_size = options[:line_size]
20
+ @data_separator = options[:data_separator]
21
+ @strip = options[:strip]
22
+ @check_count = options[:check_count]
23
+ @errors = Array.new
24
+ end
25
+
26
+ def exist?
27
+ File.exist? filename
28
+ end
29
+
30
+ def import(dataset, columns)
31
+ lines = 0
32
+ errors.clear
33
+ buffer = Array.new
34
+ File.open(filename, "rb:#{encoding}") { |fh|
35
+ while line = read_line(fh, lines)
36
+ lines += 1
37
+ values = block_given? ? yield(line) : line.split(data_separator)
38
+ raise TransporterBadFormat.new("Bad file format at line #{lines}: columns number does not match with values") unless values.count == columns.count
39
+ buffer << values
40
+ flush_data(dataset, columns, buffer) if lines % buffer_size == 0
41
+ end
42
+ flush_data dataset, columns, buffer
43
+ }
44
+ ds_count = dataset.count
45
+ raise TransporterRecordCount.new ("Lines count (#{lines}) and records count (#{ds_count}) does not match") if check_count && lines != ds_count
46
+ [lines, ds_count]
47
+ end
48
+
49
+ def export(data, append = false, &block)
50
+ count = 0
51
+ File.open(filename, append ? "ab:#{encoding}" : "wb:#{encoding}") { |fh|
52
+ lock(fh, File::LOCK_EX) { |lfh|
53
+ if data.is_a? Hash
54
+ lfh << build_line(data, &block)
55
+ count += 1
56
+ else
57
+ data.each { |row|
58
+ lfh << build_line(row, &block)
59
+ count += 1
60
+ }
61
+ end
62
+ }
63
+ }
64
+ count
65
+ end
66
+
67
+ private
68
+
69
+ def build_line(data, &block)
70
+ String.new(block_given? ? yield(data) : data.values.join(data_separator)).tap { |line|
71
+ line << line_separator
72
+ }
73
+ end
74
+
75
+ def read_line(fh, lines)
76
+ if line_size
77
+ fh.read(line_size).tap { |record|
78
+ res = fh.gets(line_separator) if strip && !fh.eof?
79
+ raise TransporterBadFormat.new("Bad file format at line #{lines+1}") unless res.nil? || res.strip.empty?
80
+ } unless fh.eof?
81
+ else
82
+ fh.gets(line_separator).tap { |line|
83
+ line.rstrip! if strip
84
+ } unless fh.eof?
85
+ end
86
+ end
87
+
88
+ def flush_data(dataset, columns, buffer)
89
+ begin
90
+ dataset.import(columns, buffer)
91
+ buffer.clear
92
+ rescue
93
+ insert_by_row(dataset, columns, buffer)
94
+ end
95
+ end
96
+
97
+ def insert_by_row(dataset, columns, buffer)
98
+ begin
99
+ buffer.each { |row|
100
+ begin
101
+ dataset.insert columns, row
102
+ rescue => err
103
+ errors << "#{err} in #{row.inspect}\n#{err.backtrace&.join("\n")}"
104
+ end
105
+ }
106
+ ensure
107
+ buffer.clear
108
+ end
109
+ end
110
+
111
+ def lock(file, mode)
112
+ if file.flock(mode)
113
+ begin
114
+ yield file
115
+ ensure
116
+ file.flock(File::LOCK_UN)
117
+ end
118
+ end
119
+ end
120
+
121
+
122
+ end
123
+
124
+ class TransporterError < StandardError; end
125
+ class TransporterBadFormat < TransporterError; end
126
+ class TransporterRecordCount < TransporterError; end
127
+
128
+
129
+ end
130
+ end
@@ -3,7 +3,7 @@
3
3
  module Tzispa
4
4
  module Data
5
5
 
6
- VERSION = '0.1.4'
6
+ VERSION = '0.2.0'
7
7
  NAME = 'Tzispa Data'
8
8
  GEM_NAME = 'tzispa_data'
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tzispa_data
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Antonio Piñero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-03 00:00:00.000000000 Z
11
+ date: 2016-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -52,6 +52,7 @@ files:
52
52
  - lib/tzispa/data/adapter_pool.rb
53
53
  - lib/tzispa/data/entity.rb
54
54
  - lib/tzispa/data/repository.rb
55
+ - lib/tzispa/data/transporter.rb
55
56
  - lib/tzispa/data/version.rb
56
57
  - lib/tzispa_data.rb
57
58
  homepage: https://github.com/japiber/tzispa_data