feedx 0.2.1 → 0.3.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 +4 -4
- data/Gemfile.lock +3 -3
- data/feedx.gemspec +2 -2
- data/lib/feedx/pusher.rb +16 -7
- data/spec/feedx/pusher_spec.rb +32 -13
- metadata +4 -7
- data/lib/feedx/pusher/recurring.rb +0 -39
- data/spec/feedx/pusher/recurring_spec.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f277d04178e84d34dbdaf5a34c0583cd8e058f7afd3780986fd4a5ba18e27e1c
|
4
|
+
data.tar.gz: b806a72c9f263a4819d13068fa347a002d5084c8f95c4c1586e843af95f683fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 381ac4112b4b9da045f52f6663f004f80404e58c533b6be0298cf55212db700ae50d7e5f0f6e4064930c266d4c3677f3f6aded9480c6191c936580810a88ee03
|
7
|
+
data.tar.gz: b90fc37870f6767b4b19b15cca79a242f36e5922c93084f2b235430ac6879e8e4877703dd1335d9b44f879db3dc79f680775e95aa3c7b0c1aad9b276ac24b6aa
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
feedx (0.
|
5
|
-
bfs
|
4
|
+
feedx (0.3.0)
|
5
|
+
bfs (>= 0.3.3)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
ast (2.4.0)
|
11
|
-
bfs (0.3.
|
11
|
+
bfs (0.3.3)
|
12
12
|
diff-lcs (1.3)
|
13
13
|
google-protobuf (3.6.1)
|
14
14
|
jaro_winkler (1.5.1)
|
data/feedx.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'feedx'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.3.0'
|
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)
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.require_paths = ['lib']
|
14
14
|
s.required_ruby_version = '>= 2.2'
|
15
15
|
|
16
|
-
s.add_dependency 'bfs'
|
16
|
+
s.add_dependency 'bfs', '>= 0.3.3'
|
17
17
|
|
18
18
|
s.add_development_dependency 'bundler'
|
19
19
|
s.add_development_dependency 'pbio'
|
data/lib/feedx/pusher.rb
CHANGED
@@ -6,6 +6,8 @@ module Feedx
|
|
6
6
|
class Pusher
|
7
7
|
autoload :Recurring, 'feedx/pusher/recurring'
|
8
8
|
|
9
|
+
META_LAST_MODIFIED = 'X-Feedx-Pusher-Last-Modified'.freeze
|
10
|
+
|
9
11
|
# See constructor.
|
10
12
|
def self.perform(url, opts={}, &block)
|
11
13
|
new(url, opts, &block).perform
|
@@ -16,6 +18,7 @@ module Feedx
|
|
16
18
|
# @option opts [Enumerable,ActiveRecord::Relation] :enum relation or enumerator to stream.
|
17
19
|
# @option opts [Symbol,Class<Feedx::Format::Abstract>] :format custom formatter. Default: from file extension.
|
18
20
|
# @option opts [Symbol,Class<Feedx::Compression::Abstract>] :compress enable compression. Default: from file extension.
|
21
|
+
# @option opts [Time,Proc] :last_modified the last modified time, used to determine if a push is necessary.
|
19
22
|
# @yield A block factory to generate the relation or enumerator.
|
20
23
|
# @yieldreturn [Enumerable,ActiveRecord::Relation] the relation or enumerator to stream.
|
21
24
|
def initialize(url, opts={}, &block)
|
@@ -25,20 +28,26 @@ module Feedx
|
|
25
28
|
@blob = BFS::Blob.new(url)
|
26
29
|
@format = detect_format(opts[:format])
|
27
30
|
@compress = detect_compress(opts[:compress])
|
31
|
+
@last_mod = opts[:last_modified]
|
28
32
|
end
|
29
33
|
|
30
|
-
def perform
|
31
|
-
@
|
34
|
+
def perform
|
35
|
+
enum = @enum.is_a?(Proc) ? @enum.call : @enum
|
36
|
+
last_mod = @last_mod.is_a?(Proc) ? @last_mod.call(enum) : @last_mod
|
37
|
+
current = (last_mod.to_f * 1000).floor
|
38
|
+
|
39
|
+
begin
|
40
|
+
previous = @blob.info.metadata[META_LAST_MODIFIED].to_i
|
41
|
+
return -1 unless current > previous
|
42
|
+
rescue BFS::FileNotFound # rubocop:disable Lint/HandleExceptions
|
43
|
+
end if current.positive?
|
44
|
+
|
45
|
+
@blob.create metadata: { META_LAST_MODIFIED => current.to_s } do |io|
|
32
46
|
@compress.wrap(io) {|w| write_all(enum, w) }
|
33
47
|
end
|
34
48
|
@blob.info.size
|
35
49
|
end
|
36
50
|
|
37
|
-
# @return [Enumerable,ActiveRecord::Relation] the relation or enumerator.
|
38
|
-
def build_enum
|
39
|
-
@enum.is_a?(Proc) ? @enum.call : @enum
|
40
|
-
end
|
41
|
-
|
42
51
|
private
|
43
52
|
|
44
53
|
def detect_format(val)
|
data/spec/feedx/pusher_spec.rb
CHANGED
@@ -17,44 +17,63 @@ RSpec.describe Feedx::Pusher do
|
|
17
17
|
%w[x y z].map {|t| model.new(t) } * 100
|
18
18
|
end
|
19
19
|
|
20
|
-
let(:
|
21
|
-
|
20
|
+
let(:bucket) { BFS::Bucket::InMem.new }
|
21
|
+
before { allow(BFS).to receive(:resolve).and_return(bucket) }
|
22
22
|
|
23
23
|
it 'should reject invalid inputs' do
|
24
24
|
expect do
|
25
|
-
described_class.perform
|
25
|
+
described_class.perform 'mock:///dir/file.txt', enum: enumerable
|
26
26
|
end.to raise_error(/unable to detect format/)
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'should push compressed JSON' do
|
30
|
-
size = described_class.perform
|
30
|
+
size = described_class.perform 'mock:///dir/file.jsonz', enum: enumerable
|
31
31
|
expect(size).to be_within(20).of(166)
|
32
|
-
expect(
|
32
|
+
expect(bucket.info('dir/file.jsonz').size).to eq(size)
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'should push plain JSON' do
|
36
|
-
size = described_class.perform
|
36
|
+
size = described_class.perform 'mock:///dir/file.json', enum: enumerable
|
37
37
|
expect(size).to eq(15900)
|
38
|
-
expect(
|
38
|
+
expect(bucket.info('dir/file.json').size).to eq(size)
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should push compressed PB' do
|
42
|
-
size = described_class.perform
|
42
|
+
size = described_class.perform 'mock:///dir/file.pbz', enum: enumerable
|
43
43
|
expect(size).to be_within(20).of(41)
|
44
|
-
expect(
|
44
|
+
expect(bucket.info('dir/file.pbz').size).to eq(size)
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'should push plain PB' do
|
48
|
-
size = described_class.perform
|
48
|
+
size = described_class.perform 'mock:///dir/file.pb', enum: enumerable
|
49
49
|
expect(size).to eq(1200)
|
50
|
-
expect(
|
50
|
+
expect(bucket.info('dir/file.pb').size).to eq(size)
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'should support factories' do
|
54
|
-
size = described_class.perform(
|
54
|
+
size = described_class.perform('mock:///dir/file.json') do
|
55
55
|
enumerable
|
56
56
|
end
|
57
57
|
expect(size).to eq(15900)
|
58
|
-
expect(
|
58
|
+
expect(bucket.info('dir/file.json').size).to eq(size)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should support last-modified' do
|
62
|
+
described_class.perform 'mock:///dir/file.json', last_modified: Time.at(1515151515), enum: enumerable
|
63
|
+
expect(bucket.info('dir/file.json').metadata).to eq('X-Feedx-Pusher-Last-Modified' => '1515151515000')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should perform conditionally' do
|
67
|
+
size = described_class.perform 'mock:///dir/file.json', last_modified: Time.at(1515151515), enum: enumerable
|
68
|
+
expect(size).to eq(15900)
|
69
|
+
|
70
|
+
size = described_class.perform 'mock:///dir/file.json', last_modified: Time.at(1515151515), enum: enumerable
|
71
|
+
expect(size).to eq(-1)
|
72
|
+
|
73
|
+
size = described_class.perform 'mock:///dir/file.json', last_modified: Time.at(1515151514), enum: enumerable
|
74
|
+
expect(size).to eq(-1)
|
75
|
+
|
76
|
+
size = described_class.perform 'mock:///dir/file.json', last_modified: Time.at(1515151516), enum: enumerable
|
77
|
+
expect(size).to eq(15900)
|
59
78
|
end
|
60
79
|
end
|
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.
|
4
|
+
version: 0.3.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: 2018-11-
|
11
|
+
date: 2018-11-26 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:
|
19
|
+
version: 0.3.3
|
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:
|
26
|
+
version: 0.3.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,14 +121,12 @@ files:
|
|
121
121
|
- lib/feedx/format/json.rb
|
122
122
|
- lib/feedx/format/protobuf.rb
|
123
123
|
- lib/feedx/pusher.rb
|
124
|
-
- lib/feedx/pusher/recurring.rb
|
125
124
|
- spec/feedx/compression/gzip_spec.rb
|
126
125
|
- spec/feedx/compression/none_spec.rb
|
127
126
|
- spec/feedx/compression_spec.rb
|
128
127
|
- spec/feedx/format/json_spec.rb
|
129
128
|
- spec/feedx/format/protobuf_spec.rb
|
130
129
|
- spec/feedx/format_spec.rb
|
131
|
-
- spec/feedx/pusher/recurring_spec.rb
|
132
130
|
- spec/feedx/pusher_spec.rb
|
133
131
|
- spec/spec_helper.rb
|
134
132
|
homepage: https://github.com/bsm/feedx
|
@@ -162,6 +160,5 @@ test_files:
|
|
162
160
|
- spec/feedx/format/json_spec.rb
|
163
161
|
- spec/feedx/format/protobuf_spec.rb
|
164
162
|
- spec/feedx/format_spec.rb
|
165
|
-
- spec/feedx/pusher/recurring_spec.rb
|
166
163
|
- spec/feedx/pusher_spec.rb
|
167
164
|
- spec/spec_helper.rb
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Feedx
|
2
|
-
class Pusher
|
3
|
-
module Recurring
|
4
|
-
DEFAULT_CHECK = proc do |enum|
|
5
|
-
enum.respond_to?(:maximum) ? enum.maximum(:updated_at).to_f : 0.0
|
6
|
-
end.freeze
|
7
|
-
|
8
|
-
# Registered pushers
|
9
|
-
def self.registry
|
10
|
-
@registry ||= {}
|
11
|
-
end
|
12
|
-
|
13
|
-
# Performs a recurring Pusher task. See see Feedx::Pusher.new for additional
|
14
|
-
# information on params and options.
|
15
|
-
#
|
16
|
-
# @param [String] name a unique task name.
|
17
|
-
# @param [Hash] opts options.
|
18
|
-
# @option [Proc] :check a custom revision check to evalute before perform.
|
19
|
-
# Receives the enum as an argument and returns a Numeric revision.
|
20
|
-
# Default: ->(enum) { enum.maximum(:updated_at).to_f }
|
21
|
-
def self.perform(name, url, opts={}, &block)
|
22
|
-
stored = registry[name]
|
23
|
-
unless stored
|
24
|
-
check = opts.delete(:check) || DEFAULT_CHECK
|
25
|
-
stored = { pusher: Feedx::Pusher.new(url, opts, &block), check: check, revision: 0 }
|
26
|
-
registry[name] = stored
|
27
|
-
end
|
28
|
-
|
29
|
-
enum = stored[:pusher].build_enum
|
30
|
-
latest = stored[:check].call(enum).to_f
|
31
|
-
return -1 unless stored[:revision] < latest
|
32
|
-
|
33
|
-
size = stored[:pusher].perform(enum)
|
34
|
-
stored[:revision] = latest
|
35
|
-
size
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Feedx::Pusher::Recurring do
|
4
|
-
let :enumerable do
|
5
|
-
enum = %w[x y z].map {|t| { title: t } } * 100
|
6
|
-
enum.instance_eval do
|
7
|
-
def maximum(*)
|
8
|
-
1515151515.0
|
9
|
-
end
|
10
|
-
end
|
11
|
-
enum
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:tempdir) { Dir.mktmpdir }
|
15
|
-
after { FileUtils.rm_rf tempdir }
|
16
|
-
after { described_class.registry.clear }
|
17
|
-
|
18
|
-
it 'should perform conditionally' do
|
19
|
-
size = described_class.perform 'test.task', "file://#{tempdir}/file.json", enum: enumerable
|
20
|
-
expect(size).to eq(4200)
|
21
|
-
expect(File.size("#{tempdir}/file.json")).to eq(size)
|
22
|
-
expect(described_class.registry).to include('test.task')
|
23
|
-
expect(described_class.registry['test.task']).to include(revision: 1515151515.0)
|
24
|
-
|
25
|
-
size = described_class.perform 'test.task', "file://#{tempdir}/file.json", enum: enumerable
|
26
|
-
expect(size).to eq(-1)
|
27
|
-
end
|
28
|
-
end
|