feedx 0.9.0 → 0.11.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.
@@ -1,22 +1,23 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Feedx::Format::Protobuf do
4
- subject { described_class.new(wio) }
5
4
  let(:wio) { StringIO.new }
5
+ let(:rio) { StringIO.open(wio.string) }
6
6
 
7
7
  it 'should encode/decode' do
8
- subject.encode(Feedx::TestCase::Model.new('X'))
9
- subject.encode(Feedx::TestCase::Model.new('Y'))
10
- subject.encode(Feedx::TestCase::Message.new(title: 'Z'))
8
+ subject.encoder wio do |enc|
9
+ enc.encode(Feedx::TestCase::Model.new('X'))
10
+ enc.encode(Feedx::TestCase::Model.new('Y'))
11
+ enc.encode(Feedx::TestCase::Message.new(title: 'Z'))
12
+ end
11
13
  expect(wio.string.bytes).to eq([3, 10, 1, 88] + [3, 10, 1, 89] + [3, 10, 1, 90])
12
14
 
13
- StringIO.open(wio.string) do |rio|
14
- fmt = described_class.new(rio)
15
- expect(fmt.decode(Feedx::TestCase::Message)).to eq(Feedx::TestCase::Message.new(title: 'X'))
16
- expect(fmt.decode(Feedx::TestCase::Message)).to eq(Feedx::TestCase::Message.new(title: 'Y'))
17
- expect(fmt.decode(Feedx::TestCase::Message)).to eq(Feedx::TestCase::Message.new(title: 'Z'))
18
- expect(fmt.decode(Feedx::TestCase::Message)).to be_nil
19
- expect(fmt).to be_eof
15
+ subject.decoder rio do |dec|
16
+ expect(dec.decode(Feedx::TestCase::Message)).to eq(Feedx::TestCase::Message.new(title: 'X'))
17
+ expect(dec.decode(Feedx::TestCase::Message)).to eq(Feedx::TestCase::Message.new(title: 'Y'))
18
+ expect(dec.decode(Feedx::TestCase::Message)).to eq(Feedx::TestCase::Message.new(title: 'Z'))
19
+ expect(dec.decode(Feedx::TestCase::Message)).to be_nil
20
+ expect(dec).to be_eof
20
21
  end
21
22
  end
22
23
  end
@@ -2,18 +2,18 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Feedx::Format do
4
4
  it 'should resolve' do
5
- expect(described_class.resolve(:json)).to eq(described_class::JSON)
6
- expect(described_class.resolve(:pb)).to eq(described_class::Protobuf)
5
+ expect(described_class.resolve(:json)).to be_instance_of(described_class::JSON)
6
+ expect(described_class.resolve(:pb)).to be_instance_of(described_class::Protobuf)
7
7
  expect { described_class.resolve(:txt) }.to raise_error(/invalid format txt/)
8
8
  end
9
9
 
10
10
  it 'should detect' do
11
- expect(described_class.detect('path/to/file.json')).to eq(described_class::JSON)
12
- expect(described_class.detect('path/to/file.jsonz')).to eq(described_class::JSON)
13
- expect(described_class.detect('path/to/file.json.gz')).to eq(described_class::JSON)
14
- expect(described_class.detect('path/to/file.pb')).to eq(described_class::Protobuf)
15
- expect(described_class.detect('path/to/file.pbz')).to eq(described_class::Protobuf)
16
- expect(described_class.detect('path/to/file.pb.z')).to eq(described_class::Protobuf)
11
+ expect(described_class.detect('path/to/file.json')).to be_instance_of(described_class::JSON)
12
+ expect(described_class.detect('path/to/file.jsonz')).to be_instance_of(described_class::JSON)
13
+ expect(described_class.detect('path/to/file.json.gz')).to be_instance_of(described_class::JSON)
14
+ expect(described_class.detect('path/to/file.pb')).to be_instance_of(described_class::Protobuf)
15
+ expect(described_class.detect('path/to/file.pbz')).to be_instance_of(described_class::Protobuf)
16
+ expect(described_class.detect('path/to/file.pb.z')).to be_instance_of(described_class::Protobuf)
17
17
  expect do
18
18
  described_class.detect('path/to/file.txt')
19
19
  end.to raise_error(/unable to detect format/)
@@ -13,13 +13,32 @@ RSpec.describe Feedx::Stream do
13
13
  end.to raise_error(/unable to detect format/)
14
14
  end
15
15
 
16
+ it 'should accept custom formats' do
17
+ format = Class.new do
18
+ def encoder(io, &block)
19
+ Feedx::Format::JSON::Encoder.open(io, &block)
20
+ end
21
+
22
+ def decoder(io, &block)
23
+ Feedx::Format::JSON::Decoder.open(io, &block)
24
+ end
25
+ end
26
+
27
+ stream = described_class.new('mock:///dir/file.txt', format: format.new)
28
+ stream.create {|s| s.encode Feedx::TestCase::Model.new('X') }
29
+
30
+ expect(bucket.read('dir/file.txt')).to eq(
31
+ %({"title":"X","updated_at":"2018-01-05 11:25:15 UTC"}\n),
32
+ )
33
+ end
34
+
16
35
  it 'should encode' do
17
36
  subject.create do |s|
18
37
  s.encode(Feedx::TestCase::Model.new('X'))
19
38
  s.encode(Feedx::TestCase::Model.new('Y'))
20
39
  end
21
40
 
22
- expect(bucket.open('dir/file.json').read).to eq(
41
+ expect(bucket.read('dir/file.json')).to eq(
23
42
  %({"title":"X","updated_at":"2018-01-05 11:25:15 UTC"}\n) +
24
43
  %({"title":"Y","updated_at":"2018-01-05 11:25:15 UTC"}\n),
25
44
  )
@@ -28,13 +28,29 @@ module Feedx
28
28
  end
29
29
  alias eql? ==
30
30
 
31
+ def updated_at
32
+ Time.at(1515151515).utc
33
+ end
34
+
31
35
  def from_json(data, *)
32
36
  hash = ::JSON.parse(data)
33
37
  @title = hash['title'] if hash.is_a?(Hash)
34
38
  end
35
39
 
36
40
  def to_json(*)
37
- ::JSON.dump(title: @title, updated_at: Time.at(1515151515).utc)
41
+ ::JSON.dump(title: @title, updated_at: updated_at)
42
+ end
43
+
44
+ def from_parquet(rec)
45
+ rec.each_pair do |name, value|
46
+ @title = value if name == 'title'
47
+ end
48
+ end
49
+
50
+ def to_parquet(schema, *)
51
+ schema.fields.map do |field|
52
+ send(field.name)
53
+ end
38
54
  end
39
55
  end
40
56
  end
data/writer.go CHANGED
@@ -39,33 +39,29 @@ func (o *WriterOptions) norm(name string) {
39
39
  // Writer encodes feeds to remote locations.
40
40
  type Writer struct {
41
41
  ctx context.Context
42
- cancel context.CancelFunc
43
-
44
42
  remote *bfs.Object
45
43
  opt WriterOptions
46
44
  num int
47
45
 
48
- bw io.WriteCloser // bfs writer
46
+ bw bfs.Writer
49
47
  cw io.WriteCloser // compression writer
50
48
  ww *bufio.Writer
51
49
  fe FormatEncoder
52
50
  }
53
51
 
54
52
  // NewWriter inits a new feed writer.
55
- func NewWriter(ctx context.Context, remote *bfs.Object, opt *WriterOptions) (*Writer, error) {
53
+ func NewWriter(ctx context.Context, remote *bfs.Object, opt *WriterOptions) *Writer {
56
54
  var o WriterOptions
57
55
  if opt != nil {
58
56
  o = *opt
59
57
  }
60
58
  o.norm(remote.Name())
61
59
 
62
- ctx, cancel := context.WithCancel(ctx)
63
60
  return &Writer{
64
61
  ctx: ctx,
65
- cancel: cancel,
66
62
  remote: remote,
67
63
  opt: o,
68
- }, nil
64
+ }
69
65
  }
70
66
 
71
67
  // Write write raw bytes to the feed.
@@ -113,13 +109,27 @@ func (w *Writer) NumWritten() int {
113
109
 
114
110
  // Discard closes the writer and discards the contents.
115
111
  func (w *Writer) Discard() error {
116
- w.cancel()
117
- return w.Commit()
112
+ err := w.close()
113
+ if w.bw != nil {
114
+ if e := w.bw.Discard(); e != nil {
115
+ err = e
116
+ }
117
+ }
118
+ return err
118
119
  }
119
120
 
120
121
  // Commit closes the writer and persists the contents.
121
122
  func (w *Writer) Commit() error {
122
- var err error
123
+ err := w.close()
124
+ if w.bw != nil {
125
+ if e := w.bw.Commit(); e != nil {
126
+ err = e
127
+ }
128
+ }
129
+ return err
130
+ }
131
+
132
+ func (w *Writer) close() (err error) {
123
133
  if w.fe != nil {
124
134
  if e := w.fe.Close(); e != nil {
125
135
  err = e
@@ -135,11 +145,6 @@ func (w *Writer) Commit() error {
135
145
  err = e
136
146
  }
137
147
  }
138
- if w.bw != nil {
139
- if e := w.bw.Close(); e != nil {
140
- err = e
141
- }
142
- }
143
148
  return err
144
149
  }
145
150
 
@@ -21,10 +21,9 @@ var _ = Describe("Writer", func() {
21
21
  })
22
22
 
23
23
  It("should write plain", func() {
24
- w, err := feedx.NewWriter(context.Background(), plain, &feedx.WriterOptions{
24
+ w := feedx.NewWriter(context.Background(), plain, &feedx.WriterOptions{
25
25
  LastMod: time.Unix(1515151515, 123456789),
26
26
  })
27
- Expect(err).NotTo(HaveOccurred())
28
27
  defer w.Discard()
29
28
 
30
29
  Expect(w.Write(bytes.Repeat([]byte{'x'}, 10000))).To(Equal(10000))
@@ -37,10 +36,9 @@ var _ = Describe("Writer", func() {
37
36
  })
38
37
 
39
38
  It("should write compressed", func() {
40
- w, err := feedx.NewWriter(context.Background(), compressed, &feedx.WriterOptions{
39
+ w := feedx.NewWriter(context.Background(), compressed, &feedx.WriterOptions{
41
40
  LastMod: time.Unix(1515151515, 123456789),
42
41
  })
43
- Expect(err).NotTo(HaveOccurred())
44
42
  defer w.Discard()
45
43
 
46
44
  Expect(w.Write(bytes.Repeat([]byte{'x'}, 10000))).To(Equal(10000))
@@ -58,7 +56,7 @@ var _ = Describe("Writer", func() {
58
56
 
59
57
  info, err := plain.Head(ctx)
60
58
  Expect(err).NotTo(HaveOccurred())
61
- Expect(info.Size).To(BeNumerically("~", 470, 10))
59
+ Expect(info.Size).To(BeNumerically("~", 370, 10))
62
60
  Expect(info.Metadata).To(Equal(bfs.Metadata{"X-Feedx-Last-Modified": "1515151515123"}))
63
61
 
64
62
  info, err = compressed.Head(ctx)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feedx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Black Square Media Ltd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-10 00:00:00.000000000 Z
11
+ date: 2020-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bfs
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: red-parquet
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,8 @@ files:
136
150
  - format_test.go
137
151
  - go.mod
138
152
  - go.sum
153
+ - internal/testdata/testdata.pb.go
154
+ - internal/testdata/testdata.proto
139
155
  - lib/feedx.rb
140
156
  - lib/feedx/cache.rb
141
157
  - lib/feedx/cache/abstract.rb
@@ -149,6 +165,7 @@ files:
149
165
  - lib/feedx/format.rb
150
166
  - lib/feedx/format/abstract.rb
151
167
  - lib/feedx/format/json.rb
168
+ - lib/feedx/format/parquet.rb
152
169
  - lib/feedx/format/protobuf.rb
153
170
  - lib/feedx/producer.rb
154
171
  - lib/feedx/pusher.rb
@@ -165,6 +182,7 @@ files:
165
182
  - spec/feedx/consumer_spec.rb
166
183
  - spec/feedx/format/abstract_spec.rb
167
184
  - spec/feedx/format/json_spec.rb
185
+ - spec/feedx/format/parquet_spec.rb
168
186
  - spec/feedx/format/protobuf_spec.rb
169
187
  - spec/feedx/format_spec.rb
170
188
  - spec/feedx/producer_spec.rb
@@ -191,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
209
  - !ruby/object:Gem::Version
192
210
  version: '0'
193
211
  requirements: []
194
- rubygems_version: 3.0.3
212
+ rubygems_version: 3.1.4
195
213
  signing_key:
196
214
  specification_version: 4
197
215
  summary: Exchange data between components via feeds
@@ -204,6 +222,7 @@ test_files:
204
222
  - spec/feedx/consumer_spec.rb
205
223
  - spec/feedx/format/abstract_spec.rb
206
224
  - spec/feedx/format/json_spec.rb
225
+ - spec/feedx/format/parquet_spec.rb
207
226
  - spec/feedx/format/protobuf_spec.rb
208
227
  - spec/feedx/format_spec.rb
209
228
  - spec/feedx/producer_spec.rb