feedx 0.6.2 → 0.6.3

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
  SHA256:
3
- metadata.gz: 7e5d88effb5a873a2cb2e16d4c7f824b824ef2f93bc306c500b3f97314b7d91c
4
- data.tar.gz: be78ba37f5869fc6c2e026f2c1809dd083e7a0d02a55f66be3e9d555a6c7dc58
3
+ metadata.gz: 1f4710e181ac3c987f7b02ebc976cf70bbc4c9826139823bca58620d94aa994a
4
+ data.tar.gz: 273951be43e9e8ac3473bfccf428cf2860c34dd4c0869b86f726446c477c2e7f
5
5
  SHA512:
6
- metadata.gz: 9dab374c591498c3a23a0f2fab33fc8268c3c6028205b83c5483a4ebe27e468f00b05dfeb1200b237f358997f1d01654bec61fc1bb6fdd5c89fe317dba1e562d
7
- data.tar.gz: 71d086bc0f43ef382e354c710badb8b0f10f3cab75dca6f79abda448add5115c2c82ab26ab9a4b503cab23960918fd768d4b505d3ebb4a66156341d334525de1
6
+ metadata.gz: 862eeb21fda2add182866fdb686adab45091d585a9880565b7e12c2ef3240ecc3982ec09e0370f1e4734d57ac44aa97cd5fcd702215c84d9534e5eab5ba9b648
7
+ data.tar.gz: fc10bdbfea9922ca29d3d0967ab8a1aa14330b914b1e07972ca61e040620d2ccdcd710e0eb63860001feb3c366097652b825fd4660e847449edfeecdbd3232e0
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- feedx (0.6.2)
4
+ feedx (0.6.3)
5
5
  bfs (>= 0.3.4)
6
6
 
7
7
  GEM
@@ -17,8 +17,8 @@ type ConsumerOptions struct {
17
17
  Interval time.Duration
18
18
 
19
19
  // AfterSync callbacks are triggered after each sync, receiving
20
- // the updated status and error (if occurred).
21
- AfterSync func(updated bool, consumer Consumer, err error)
20
+ // the sync state and error (if occurred).
21
+ AfterSync func(*ConsumerSync, error)
22
22
  }
23
23
 
24
24
  func (o *ConsumerOptions) norm(name string) error {
@@ -29,6 +29,18 @@ func (o *ConsumerOptions) norm(name string) error {
29
29
  return nil
30
30
  }
31
31
 
32
+ // ConsumerSync contains the state of the last sync.
33
+ type ConsumerSync struct {
34
+ // Consumer exposes the current consumer state.
35
+ Consumer
36
+ // Updated indicates is the sync resulted in an update.
37
+ Updated bool
38
+ // PreviousData references the data before the update.
39
+ // It allows to apply finalizers to data structures created by ConsumeFunc.
40
+ // This is only set when an update happened.
41
+ PreviousData interface{}
42
+ }
43
+
32
44
  // ConsumeFunc is a parsing callback which is run by the consumer every sync interval.
33
45
  type ConsumeFunc func(FormatDecoder) (data interface{}, err error)
34
46
 
@@ -137,7 +149,7 @@ func (c *consumer) Close() error {
137
149
  return nil
138
150
  }
139
151
 
140
- func (c *consumer) sync(force bool) (bool, error) {
152
+ func (c *consumer) sync(force bool) (*ConsumerSync, error) {
141
153
  defer func() {
142
154
  atomic.StoreInt64(&c.lastSync, timestampFromTime(time.Now()).Millis())
143
155
  }()
@@ -145,32 +157,37 @@ func (c *consumer) sync(force bool) (bool, error) {
145
157
  // retrieve original last modified time
146
158
  lastMod, err := remoteLastModified(c.ctx, c.remote)
147
159
  if err != nil {
148
- return false, err
160
+ return nil, err
149
161
  }
150
162
 
151
163
  // skip update if not forced or modified
152
164
  if lastMod.Millis() == atomic.LoadInt64(&c.lastMod) && !force {
153
- return false, nil
165
+ return &ConsumerSync{Consumer: c}, nil
154
166
  }
155
167
 
156
168
  // open remote reader
157
169
  reader, err := NewReader(c.ctx, c.remote, &c.opt.ReaderOptions)
158
170
  if err != nil {
159
- return false, err
171
+ return nil, err
160
172
  }
161
173
  defer reader.Close()
162
174
 
163
175
  // consume feed
164
176
  data, err := c.cfn(reader)
165
177
  if err != nil {
166
- return false, err
178
+ return nil, err
167
179
  }
168
180
 
169
181
  // update stores
182
+ previous := c.data.Load()
170
183
  c.data.Store(data)
171
184
  atomic.StoreInt64(&c.numRead, int64(reader.NumRead()))
172
185
  atomic.StoreInt64(&c.lastMod, lastMod.Millis())
173
- return true, nil
186
+ return &ConsumerSync{
187
+ Consumer: c,
188
+ Updated: true,
189
+ PreviousData: previous,
190
+ }, nil
174
191
  }
175
192
 
176
193
  func (c *consumer) loop() {
@@ -182,9 +199,9 @@ func (c *consumer) loop() {
182
199
  case <-c.ctx.Done():
183
200
  return
184
201
  case <-ticker.C:
185
- updated, err := c.sync(false)
202
+ state, err := c.sync(false)
186
203
  if c.opt.AfterSync != nil {
187
- c.opt.AfterSync(updated, c, err)
204
+ c.opt.AfterSync(state, err)
188
205
  }
189
206
  }
190
207
  }
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'feedx'
3
- s.version = '0.6.2'
3
+ s.version = '0.6.3'
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)
@@ -5,6 +5,12 @@ module Feedx
5
5
  autoload :Protobuf, 'feedx/format/protobuf'
6
6
 
7
7
  class << self
8
+ def register(ext, kind)
9
+ raise ArgumentError, "#{kind} is not a subclass of Feedx::Format::Abstract" unless kind.is_a?(Class) && kind < Abstract
10
+
11
+ registry[ext.to_s] = kind
12
+ end
13
+
8
14
  def resolve(name)
9
15
  _resolve(name) || raise(ArgumentError, "invalid format #{name}")
10
16
  end
@@ -24,13 +30,23 @@ module Feedx
24
30
 
25
31
  private
26
32
 
33
+ def registry
34
+ @registry ||= {
35
+ 'json' => :JSON,
36
+ 'pb' => :Protobuf,
37
+ 'proto' => :Protobuf,
38
+ 'protobuf' => :Protobuf,
39
+ }
40
+ end
41
+
27
42
  def _resolve(name)
28
- case name.to_s
29
- when 'pb', 'proto', 'protobuf'
30
- Protobuf
31
- when 'json'
32
- JSON
43
+ name = name.to_s
44
+ klass = registry[name]
45
+ if klass.is_a?(Symbol)
46
+ klass = const_get(klass)
47
+ registry[name.to_s] = klass
33
48
  end
49
+ klass
34
50
  end
35
51
  end
36
52
  end
@@ -24,8 +24,8 @@ type ProducerOptions struct {
24
24
  LastModCheck func(context.Context) (time.Time, error)
25
25
 
26
26
  // AfterPush callbacks are triggered after each push cycle, receiving
27
- // the updated status and error (if occurred).
28
- AfterPush func(updated bool, consumer *Producer, err error)
27
+ // the push state and error (if occurred).
28
+ AfterPush func(*ProducerPush, error)
29
29
  }
30
30
 
31
31
  func (o *ProducerOptions) norm(name string) error {
@@ -36,6 +36,14 @@ func (o *ProducerOptions) norm(name string) error {
36
36
  return nil
37
37
  }
38
38
 
39
+ // ProducerPush contains the state of the last push.
40
+ type ProducerPush struct {
41
+ // Producer exposes the current producer state.
42
+ *Producer
43
+ // Updated indicates is the push resulted in an update.
44
+ Updated bool
45
+ }
46
+
39
47
  // Producer (continously) produces a feed.
40
48
  type Producer struct {
41
49
  remote *bfs.Object
@@ -120,7 +128,7 @@ func (p *Producer) Close() error {
120
128
  return nil
121
129
  }
122
130
 
123
- func (p *Producer) push() (bool, error) {
131
+ func (p *Producer) push() (*ProducerPush, error) {
124
132
  start := time.Now()
125
133
  atomic.StoreInt64(&p.lastPush, timestampFromTime(start).Millis())
126
134
 
@@ -130,7 +138,7 @@ func (p *Producer) push() (bool, error) {
130
138
  if p.opt.LastModCheck != nil {
131
139
  modTime, err := p.opt.LastModCheck(p.ctx)
132
140
  if err != nil {
133
- return false, err
141
+ return nil, err
134
142
  }
135
143
  wopt.LastMod = modTime
136
144
  }
@@ -138,31 +146,34 @@ func (p *Producer) push() (bool, error) {
138
146
  // retrieve original last modified time
139
147
  lastMod, err := remoteLastModified(p.ctx, p.remote)
140
148
  if err != nil {
141
- return false, err
149
+ return nil, err
142
150
  }
143
151
 
144
152
  // skip push if not modified
145
153
  if lastMod.Time().Equal(wopt.LastMod) {
146
- return false, nil
154
+ return &ProducerPush{Producer: p}, nil
147
155
  }
148
156
 
149
157
  writer, err := NewWriter(p.ctx, p.remote, &wopt)
150
158
  if err != nil {
151
- return false, err
159
+ return nil, err
152
160
  }
153
161
  defer writer.Discard()
154
162
 
155
163
  if err := p.pfn(writer); err != nil {
156
- return false, err
164
+ return nil, err
157
165
  }
158
166
 
159
167
  if err := writer.Commit(); err != nil {
160
- return false, err
168
+ return nil, err
161
169
  }
162
170
 
163
171
  atomic.StoreInt64(&p.numWritten, int64(writer.NumWritten()))
164
172
  atomic.StoreInt64(&p.lastMod, timestampFromTime(wopt.LastMod).Millis())
165
- return true, nil
173
+ return &ProducerPush{
174
+ Producer: p,
175
+ Updated: true,
176
+ }, nil
166
177
  }
167
178
 
168
179
  func (p *Producer) loop() {
@@ -174,9 +185,9 @@ func (p *Producer) loop() {
174
185
  case <-p.ctx.Done():
175
186
  return
176
187
  case <-ticker.C:
177
- updated, err := p.push()
188
+ state, err := p.push()
178
189
  if p.opt.AfterPush != nil {
179
- p.opt.AfterPush(updated, p, err)
190
+ p.opt.AfterPush(state, err)
180
191
  }
181
192
  }
182
193
  }
data/writer.go CHANGED
@@ -1,6 +1,7 @@
1
1
  package feedx
2
2
 
3
3
  import (
4
+ "bufio"
4
5
  "context"
5
6
  "fmt"
6
7
  "io"
@@ -55,6 +56,7 @@ type Writer struct {
55
56
 
56
57
  bw io.WriteCloser // bfs writer
57
58
  cw io.WriteCloser // compression writer
59
+ ww *bufio.Writer
58
60
  fe FormatEncoder
59
61
  }
60
62
 
@@ -96,8 +98,12 @@ func (w *Writer) Encode(v interface{}) error {
96
98
  w.cw = cw
97
99
  }
98
100
 
101
+ if w.ww == nil {
102
+ w.ww = bufio.NewWriter(w.cw)
103
+ }
104
+
99
105
  if w.fe == nil {
100
- fe, err := w.opt.Format.NewEncoder(w.cw)
106
+ fe, err := w.opt.Format.NewEncoder(w.ww)
101
107
  if err != nil {
102
108
  return err
103
109
  }
@@ -131,6 +137,11 @@ func (w *Writer) Commit() error {
131
137
  err = e
132
138
  }
133
139
  }
140
+ if w.ww != nil {
141
+ if e := w.ww.Flush(); e != nil {
142
+ err = e
143
+ }
144
+ }
134
145
  if w.cw != nil {
135
146
  if e := w.cw.Close(); e != nil {
136
147
  err = e
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.6.2
4
+ version: 0.6.3
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-05-17 00:00:00.000000000 Z
11
+ date: 2019-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bfs