feedx 0.7.1 → 0.7.2
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 +4 -4
- data/.rubocop.yml +3 -0
- data/.travis.yml +5 -0
- data/Gemfile.lock +8 -8
- data/feedx.gemspec +3 -3
- data/lib/feedx.rb +2 -0
- data/lib/feedx/cache.rb +7 -0
- data/lib/feedx/cache/abstract.rb +35 -0
- data/lib/feedx/cache/memory.rb +30 -0
- data/lib/feedx/cache/value.rb +25 -0
- data/lib/feedx/consumer.rb +47 -0
- data/lib/feedx/format/abstract.rb +2 -2
- data/lib/feedx/format/json.rb +2 -2
- data/lib/feedx/producer.rb +12 -10
- data/spec/feedx/cache/memory_spec.rb +23 -0
- data/spec/feedx/cache/value_spec.rb +19 -0
- data/spec/feedx/consumer_spec.rb +45 -0
- data/spec/spec_helper.rb +1 -1
- metadata +16 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c294d0811dec65d1fce8a44fe2e18dbe08ac0bffee8d56c6b1d96bdac63e9366
|
4
|
+
data.tar.gz: e6172cbf1f728569624a928dcf2a22c3a9a87824ed6cfd8fddaf834d1e526d8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64f69d35aa2cdca873e223b0f959a404dacebe03b07a8ca77796a10d5d6dfc06b4f7b9e7ee3bbfcfa03c23656399038324088a19d8e643636d0d3f3408af7b4b
|
7
|
+
data.tar.gz: fb2e106e250693c5756edecf6d98df7115f8e8b33f4fca01ade0c3c568eb756215e6efa967d36099fdb055e4f77a26f68aebc207d9f62bb82c4748fb193d8ec7
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
feedx (0.7.
|
5
|
-
bfs (>= 0.
|
4
|
+
feedx (0.7.2)
|
5
|
+
bfs (>= 0.4.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
ast (2.4.0)
|
11
|
-
bfs (0.
|
11
|
+
bfs (0.4.0)
|
12
12
|
diff-lcs (1.3)
|
13
13
|
google-protobuf (3.8.0)
|
14
|
-
jaro_winkler (1.5.
|
14
|
+
jaro_winkler (1.5.3)
|
15
15
|
parallel (1.17.0)
|
16
16
|
parser (2.6.3.0)
|
17
17
|
ast (~> 2.4.0)
|
@@ -23,12 +23,12 @@ GEM
|
|
23
23
|
rspec-core (~> 3.8.0)
|
24
24
|
rspec-expectations (~> 3.8.0)
|
25
25
|
rspec-mocks (~> 3.8.0)
|
26
|
-
rspec-core (3.8.
|
26
|
+
rspec-core (3.8.1)
|
27
27
|
rspec-support (~> 3.8.0)
|
28
28
|
rspec-expectations (3.8.4)
|
29
29
|
diff-lcs (>= 1.2.0, < 2.0)
|
30
30
|
rspec-support (~> 3.8.0)
|
31
|
-
rspec-mocks (3.8.
|
31
|
+
rspec-mocks (3.8.1)
|
32
32
|
diff-lcs (>= 1.2.0, < 2.0)
|
33
33
|
rspec-support (~> 3.8.0)
|
34
34
|
rspec-support (3.8.2)
|
@@ -39,8 +39,8 @@ GEM
|
|
39
39
|
rainbow (>= 2.2.2, < 4.0)
|
40
40
|
ruby-progressbar (~> 1.7)
|
41
41
|
unicode-display_width (>= 1.4.0, < 1.7)
|
42
|
-
rubocop-performance (1.
|
43
|
-
rubocop (>= 0.
|
42
|
+
rubocop-performance (1.4.0)
|
43
|
+
rubocop (>= 0.71.0)
|
44
44
|
ruby-progressbar (1.10.1)
|
45
45
|
unicode-display_width (1.6.0)
|
46
46
|
|
data/feedx.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'feedx'
|
3
|
-
s.version = '0.7.
|
3
|
+
s.version = '0.7.2'
|
4
4
|
s.authors = ['Black Square Media Ltd']
|
5
5
|
s.email = ['info@blacksquaremedia.com']
|
6
6
|
s.summary = %(Exchange data between components via feeds)
|
@@ -11,9 +11,9 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^spec/}) }
|
12
12
|
s.test_files = `git ls-files -z -- spec/*`.split("\x0")
|
13
13
|
s.require_paths = ['lib']
|
14
|
-
s.required_ruby_version = '>= 2.
|
14
|
+
s.required_ruby_version = '>= 2.4'
|
15
15
|
|
16
|
-
s.add_dependency 'bfs', '>= 0.
|
16
|
+
s.add_dependency 'bfs', '>= 0.4.0'
|
17
17
|
|
18
18
|
s.add_development_dependency 'bundler'
|
19
19
|
s.add_development_dependency 'pbio'
|
data/lib/feedx.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module Feedx
|
2
2
|
META_LAST_MODIFIED = 'x-feedx-last-modified'.freeze
|
3
3
|
|
4
|
+
autoload :Cache, 'feedx/cache'
|
4
5
|
autoload :Compression, 'feedx/compression'
|
6
|
+
autoload :Consumer, 'feedx/consumer'
|
5
7
|
autoload :Format, 'feedx/format'
|
6
8
|
autoload :Stream, 'feedx/stream'
|
7
9
|
autoload :Producer, 'feedx/producer'
|
data/lib/feedx/cache.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
class Feedx::Cache::Abstract
|
2
|
+
# Clears cache.
|
3
|
+
def clear
|
4
|
+
raise 'Not implemented'
|
5
|
+
end
|
6
|
+
|
7
|
+
# Read reads a key.
|
8
|
+
def read(_key, **_opts)
|
9
|
+
raise 'Not implemented'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Write writes a key/value pair.
|
13
|
+
def write(_key, _value, **_opts)
|
14
|
+
raise 'Not implemented'
|
15
|
+
end
|
16
|
+
|
17
|
+
# Fetches data from the cache, using the given key.
|
18
|
+
# The optional block will be evaluated and the result stored in the cache
|
19
|
+
# in the event of a cache miss.
|
20
|
+
def fetch(key, **opts)
|
21
|
+
value = read(key, **opts)
|
22
|
+
|
23
|
+
if block_given?
|
24
|
+
value ||= yield
|
25
|
+
write(key, value, **opts) if value
|
26
|
+
end
|
27
|
+
|
28
|
+
value
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Feedx::Abstract::Value] returns a wrapper around a single value.
|
32
|
+
def value(key)
|
33
|
+
Feedx::Cache::Value.new(self, key)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
3
|
+
# Thread-safe in-memory cache. Use for testing only.
|
4
|
+
class Feedx::Cache::Memory < Feedx::Cache::Abstract
|
5
|
+
def initialize
|
6
|
+
@monitor = Monitor.new
|
7
|
+
@entries = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Clear empties cache.
|
11
|
+
def clear
|
12
|
+
@monitor.synchronize do
|
13
|
+
@entries.clear
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Read reads a key.
|
18
|
+
def read(key, **)
|
19
|
+
@monitor.synchronize do
|
20
|
+
@entries[key]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Write writes a key.
|
25
|
+
def write(key, value, **)
|
26
|
+
@monitor.synchronize do
|
27
|
+
@entries[key] = value.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# A single value inside a cache.
|
2
|
+
class Feedx::Cache::Value
|
3
|
+
attr_reader :key
|
4
|
+
|
5
|
+
def initialize(cache, key)
|
6
|
+
@cache = cache
|
7
|
+
@key = key
|
8
|
+
end
|
9
|
+
|
10
|
+
# Read the key.
|
11
|
+
def read(**opts)
|
12
|
+
@cache.read(@key, **opts)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Write a value.
|
16
|
+
def write(value, **opts)
|
17
|
+
@cache.write(@key, value, **opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Fetches data. The optional block will be evaluated and the
|
21
|
+
# result stored in the cache under the key in the event of a cache miss.
|
22
|
+
def fetch(**opts, &block)
|
23
|
+
@cache.fetch(@key, **opts, &block)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'bfs'
|
3
|
+
require 'feedx'
|
4
|
+
|
5
|
+
module Feedx
|
6
|
+
# Consumes an enumerates over a feed.
|
7
|
+
class Consumer
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
# See constructor.
|
11
|
+
def self.each(url, klass, opts={}, &block)
|
12
|
+
new(url, klass, opts).each(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [String] url the destination URL.
|
16
|
+
# @param [Class] klass the record class.
|
17
|
+
# @param [Hash] opts options
|
18
|
+
# @option opts [Symbol,Class<Feedx::Format::Abstract>] :format custom formatter. Default: from file extension.
|
19
|
+
# @option opts [Hash] :format_options format decode options. Default: {}.
|
20
|
+
# @option opts [Symbol,Class<Feedx::Compression::Abstract>] :compress enable compression. Default: from file extension.
|
21
|
+
# @option opts [Feedx::Cache::Value] :cache cache value to store remote last modified time and consume conditionally.
|
22
|
+
def initialize(url, klass, opts={})
|
23
|
+
@klass = klass
|
24
|
+
@stream = Feedx::Stream.new(url, opts)
|
25
|
+
@fmt_opts = opts[:format_options] || {}
|
26
|
+
@cache = opts[:cache]
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Boolean] returns true if performed.
|
30
|
+
def each(&block)
|
31
|
+
remote_rev = nil
|
32
|
+
|
33
|
+
if @cache
|
34
|
+
local_rev = @cache.read.to_i
|
35
|
+
remote_rev = @stream.blob.info.metadata[META_LAST_MODIFIED].to_i
|
36
|
+
return false if remote_rev.positive? && remote_rev <= local_rev
|
37
|
+
end
|
38
|
+
|
39
|
+
@stream.open do |fmt|
|
40
|
+
fmt.decode_each(@klass, **@fmt_opts, &block)
|
41
|
+
end
|
42
|
+
@cache.write(remote_rev) if @cache && remote_rev
|
43
|
+
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -9,9 +9,9 @@ class Feedx::Format::Abstract
|
|
9
9
|
|
10
10
|
def decode_each(klass, **opts)
|
11
11
|
if block_given?
|
12
|
-
yield decode(klass, opts) until eof?
|
12
|
+
yield decode(klass, **opts) until eof?
|
13
13
|
else
|
14
|
-
Enumerator.new {|y| y << decode(klass, opts) until eof? }
|
14
|
+
Enumerator.new {|y| y << decode(klass, **opts) until eof? }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
data/lib/feedx/format/json.rb
CHANGED
data/lib/feedx/producer.rb
CHANGED
@@ -3,7 +3,7 @@ require 'bfs'
|
|
3
3
|
require 'feedx'
|
4
4
|
|
5
5
|
module Feedx
|
6
|
-
# Produces a relation as
|
6
|
+
# Produces a relation as an encoded feed to a remote location.
|
7
7
|
class Producer
|
8
8
|
# See constructor.
|
9
9
|
def self.perform(url, opts={}, &block)
|
@@ -14,6 +14,7 @@ module Feedx
|
|
14
14
|
# @param [Hash] opts options
|
15
15
|
# @option opts [Enumerable,ActiveRecord::Relation] :enum relation or enumerator to stream.
|
16
16
|
# @option opts [Symbol,Class<Feedx::Format::Abstract>] :format custom formatter. Default: from file extension.
|
17
|
+
# @option opts [Hash] :format_options format encode options. Default: {}.
|
17
18
|
# @option opts [Symbol,Class<Feedx::Compression::Abstract>] :compress enable compression. Default: from file extension.
|
18
19
|
# @option opts [Time,Proc] :last_modified the last modified time, used to determine if a push is necessary.
|
19
20
|
# @yield A block factory to generate the relation or enumerator.
|
@@ -22,24 +23,25 @@ module Feedx
|
|
22
23
|
@enum = opts[:enum] || block
|
23
24
|
raise ArgumentError, "#{self.class.name}.new expects an :enum option or a block factory" unless @enum
|
24
25
|
|
25
|
-
@stream
|
26
|
+
@stream = Feedx::Stream.new(url, opts)
|
26
27
|
@last_mod = opts[:last_modified]
|
28
|
+
@fmt_opts = opts[:format_options] || {}
|
27
29
|
end
|
28
30
|
|
29
31
|
def perform
|
30
|
-
enum
|
31
|
-
last_mod
|
32
|
-
|
32
|
+
enum = @enum.is_a?(Proc) ? @enum.call : @enum
|
33
|
+
last_mod = @last_mod.is_a?(Proc) ? @last_mod.call(enum) : @last_mod
|
34
|
+
local_rev = last_mod.is_a?(Integer) ? last_mod : (last_mod.to_f * 1000).floor
|
33
35
|
|
34
36
|
begin
|
35
|
-
|
36
|
-
return -1 unless
|
37
|
+
remote_rev = @stream.blob.info.metadata[META_LAST_MODIFIED].to_i
|
38
|
+
return -1 unless local_rev > remote_rev
|
37
39
|
rescue BFS::FileNotFound # rubocop:disable Lint/HandleExceptions
|
38
|
-
end if
|
40
|
+
end if local_rev.positive?
|
39
41
|
|
40
|
-
@stream.create metadata: { META_LAST_MODIFIED =>
|
42
|
+
@stream.create metadata: { META_LAST_MODIFIED => local_rev.to_s } do |fmt|
|
41
43
|
iter = enum.respond_to?(:find_each) ? :find_each : :each
|
42
|
-
enum.send(iter) {|rec| fmt.encode(rec) }
|
44
|
+
enum.send(iter) {|rec| fmt.encode(rec, **@fmt_opts) }
|
43
45
|
end
|
44
46
|
@stream.blob.info.size
|
45
47
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Feedx::Cache::Memory do
|
4
|
+
it 'should read/write' do
|
5
|
+
expect(subject.fetch('key')).to be_nil
|
6
|
+
expect(subject.fetch('key') { 'value' }).to eq('value')
|
7
|
+
expect(subject.fetch('key')).to eq('value')
|
8
|
+
expect(subject.fetch('key') { 'other' }).to eq('value')
|
9
|
+
expect(subject.fetch('key')).to eq('value')
|
10
|
+
|
11
|
+
subject.write('key', 'new-value')
|
12
|
+
expect(subject.read('key')).to eq('new-value')
|
13
|
+
expect(subject.fetch('key')).to eq('new-value')
|
14
|
+
|
15
|
+
subject.clear
|
16
|
+
expect(subject.fetch('key')).to be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should write strings' do
|
20
|
+
subject.write('key', 5)
|
21
|
+
expect(subject.read('key')).to eq('5')
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Feedx::Cache::Value do
|
4
|
+
subject do
|
5
|
+
described_class.new(Feedx::Cache::Memory.new, 'key')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should read/write' do
|
9
|
+
expect(subject.fetch).to be_nil
|
10
|
+
expect(subject.fetch { 'value' }).to eq('value')
|
11
|
+
expect(subject.fetch).to eq('value')
|
12
|
+
expect(subject.fetch { 'other' }).to eq('value')
|
13
|
+
expect(subject.fetch).to eq('value')
|
14
|
+
|
15
|
+
subject.write('new-value')
|
16
|
+
expect(subject.read).to eq('new-value')
|
17
|
+
expect(subject.fetch).to eq('new-value')
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Feedx::Consumer do
|
4
|
+
let(:bucket) { BFS::Bucket::InMem.new }
|
5
|
+
let(:klass) { Feedx::TestCase::Model }
|
6
|
+
let(:cache) { Feedx::Cache::Memory.new.value('my-consumer') }
|
7
|
+
before { allow(BFS).to receive(:resolve).and_return(bucket) }
|
8
|
+
|
9
|
+
it 'should reject invalid inputs' do
|
10
|
+
expect do
|
11
|
+
described_class.each('mock:///dir/file.txt', klass) {}
|
12
|
+
end.to raise_error(/unable to detect format/)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should consume feeds' do
|
16
|
+
url = mock_produce!
|
17
|
+
csm = described_class.new(url, klass)
|
18
|
+
expect(csm).to be_a(Enumerable)
|
19
|
+
|
20
|
+
cnt = csm.count do |rec|
|
21
|
+
expect(rec).to be_instance_of(klass)
|
22
|
+
true
|
23
|
+
end
|
24
|
+
expect(cnt).to eq(300)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should perform conditionally' do
|
28
|
+
url = mock_produce! last_modified: Time.at(1515151515)
|
29
|
+
expect(described_class.new(url, klass, cache: cache).count).to eq(300)
|
30
|
+
expect(described_class.new(url, klass, cache: cache).count).to eq(0)
|
31
|
+
|
32
|
+
url = mock_produce!
|
33
|
+
expect(described_class.new(url, klass, cache: cache).count).to eq(300)
|
34
|
+
expect(described_class.new(url, klass, cache: cache).count).to eq(300)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def mock_produce!(opts={})
|
40
|
+
url = 'mock:///dir/file.json'
|
41
|
+
opts[:enum] ||= %w[x y z].map {|t| Feedx::TestCase::Model.new(t) } * 100
|
42
|
+
Feedx::Producer.perform url, opts
|
43
|
+
url
|
44
|
+
end
|
45
|
+
end
|
data/spec/spec_helper.rb
CHANGED
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.7.
|
4
|
+
version: 0.7.2
|
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-06-
|
11
|
+
date: 2019-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bfs
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.4.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.4.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,10 +137,15 @@ files:
|
|
137
137
|
- go.mod
|
138
138
|
- go.sum
|
139
139
|
- lib/feedx.rb
|
140
|
+
- lib/feedx/cache.rb
|
141
|
+
- lib/feedx/cache/abstract.rb
|
142
|
+
- lib/feedx/cache/memory.rb
|
143
|
+
- lib/feedx/cache/value.rb
|
140
144
|
- lib/feedx/compression.rb
|
141
145
|
- lib/feedx/compression/abstract.rb
|
142
146
|
- lib/feedx/compression/gzip.rb
|
143
147
|
- lib/feedx/compression/none.rb
|
148
|
+
- lib/feedx/consumer.rb
|
144
149
|
- lib/feedx/format.rb
|
145
150
|
- lib/feedx/format/abstract.rb
|
146
151
|
- lib/feedx/format/json.rb
|
@@ -152,9 +157,12 @@ files:
|
|
152
157
|
- producer_test.go
|
153
158
|
- reader.go
|
154
159
|
- reader_test.go
|
160
|
+
- spec/feedx/cache/memory_spec.rb
|
161
|
+
- spec/feedx/cache/value_spec.rb
|
155
162
|
- spec/feedx/compression/gzip_spec.rb
|
156
163
|
- spec/feedx/compression/none_spec.rb
|
157
164
|
- spec/feedx/compression_spec.rb
|
165
|
+
- spec/feedx/consumer_spec.rb
|
158
166
|
- spec/feedx/format/abstract_spec.rb
|
159
167
|
- spec/feedx/format/json_spec.rb
|
160
168
|
- spec/feedx/format/protobuf_spec.rb
|
@@ -176,7 +184,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
176
184
|
requirements:
|
177
185
|
- - ">="
|
178
186
|
- !ruby/object:Gem::Version
|
179
|
-
version: '2.
|
187
|
+
version: '2.4'
|
180
188
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
189
|
requirements:
|
182
190
|
- - ">="
|
@@ -188,9 +196,12 @@ signing_key:
|
|
188
196
|
specification_version: 4
|
189
197
|
summary: Exchange data between components via feeds
|
190
198
|
test_files:
|
199
|
+
- spec/feedx/cache/memory_spec.rb
|
200
|
+
- spec/feedx/cache/value_spec.rb
|
191
201
|
- spec/feedx/compression/gzip_spec.rb
|
192
202
|
- spec/feedx/compression/none_spec.rb
|
193
203
|
- spec/feedx/compression_spec.rb
|
204
|
+
- spec/feedx/consumer_spec.rb
|
194
205
|
- spec/feedx/format/abstract_spec.rb
|
195
206
|
- spec/feedx/format/json_spec.rb
|
196
207
|
- spec/feedx/format/protobuf_spec.rb
|