sequence-sdk 2.1 → 2.2.rc.1

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: da2edb02eda3ac971bd102181b56b78339a16a30d12c7c06c123569a09180584
4
- data.tar.gz: a8e9ffb7f528e3679f817ab2b06e1399ed90013d474601dcbb01f8e92e2a5cd1
3
+ metadata.gz: 6246691bbc9fe8915c626d2013e33c0dbb4950606d3a56a505365889e26c1660
4
+ data.tar.gz: 18be34a81476f9cb75855aef2126f68e2fa36f8849ea727e1bef278b40a442c3
5
5
  SHA512:
6
- metadata.gz: 807d33a14ca05d631003907294f6e2ca6f0618838615907853feb071f661a98268b26b5f70216670a8d36ac2c2ae32540cacd02ffba18461655c8729bf784df7
7
- data.tar.gz: ea5d6ec64d2809b8a744efdf178b5ffde5721499f706652427c2dbe0e5ff556493b1fa327f09835d0150917e8bb1198950997f0c07b132002cb9b1df008257ab
6
+ metadata.gz: 88bbd9ececed4673dd0dc2547ca3e1feb1a02bcb5e23366dbe906f5106832f6da18c2c0114e2cd3de15bb50911569b929df56c75de597db773e39c329090a821
7
+ data.tar.gz: b4a4340dd743d635d52a17c6977e5ed589ed38b344026054337273fdb2d00f2d21aeeb7a0217aff0b12deedc10ef1e8f4c62fad5f69c55e4e0c4ff9b0d263e32
@@ -87,6 +87,17 @@ module Sequence
87
87
  ListQuery.new(client, filter: filter, filter_params: filter_params)
88
88
  end
89
89
 
90
+ # Update an action's tags.
91
+ # @param id [String]
92
+ # The ID of the action.
93
+ # @param tags [Hash]
94
+ # A new set of tags, which will replace the existing tags.
95
+ # @return [void]
96
+ def update_tags(id:, tags: nil)
97
+ raise ArgumentError, ':id cannot be blank' if id == ''
98
+ client.session.request('update-action-tags', id: id, tags: tags)
99
+ end
100
+
90
101
  # Execute a query, returning an enumerable over sums of actions.
91
102
  # @param filter [String]
92
103
  # A filter expression.
@@ -6,6 +6,7 @@ require_relative './dev_utils'
6
6
  require_relative './feed'
7
7
  require_relative './flavor'
8
8
  require_relative './http_wrapper'
9
+ require_relative './index'
9
10
  require_relative './key'
10
11
  require_relative './stats'
11
12
  require_relative './token'
@@ -28,14 +29,11 @@ module Sequence
28
29
  raise ArgumentError, ':credential cannot be blank'
29
30
  end
30
31
 
31
- addr = ENV['SEQADDR'] || 'api.seq.com'
32
- api = HttpWrapper.new('https://' + addr, credential)
33
32
  @opts = {
34
- addr: addr,
35
33
  credential: credential,
36
34
  ledger_name: ledger_name,
37
- team_name: team_name(api),
38
35
  }
36
+ @session = Session.new(@opts)
39
37
  end
40
38
 
41
39
  # @private
@@ -45,23 +43,31 @@ module Sequence
45
43
 
46
44
  # @private
47
45
  # @return [Session]
48
- def session
49
- @session ||= Session.new(@opts)
50
- end
46
+ attr_reader :session
51
47
 
52
48
  # @return [Account::ClientModule]
53
49
  def accounts
54
50
  @accounts ||= Account::ClientModule.new(self)
55
51
  end
56
52
 
53
+ # @return [Action::ClientModule]
54
+ def actions
55
+ @actions ||= Action::ClientModule.new(self)
56
+ end
57
+
58
+ # @return [Feed::ClientModule]
59
+ def feeds
60
+ @feeds ||= Feed::ClientModule.new(self)
61
+ end
62
+
57
63
  # @return [Flavor::ClientModule]
58
64
  def flavors
59
65
  @flavors ||= Flavor::ClientModule.new(self)
60
66
  end
61
67
 
62
- # @return [Action::ClientModule]
63
- def actions
64
- @actions ||= Action::ClientModule.new(self)
68
+ # @return [Index::ClientModule]
69
+ def indexes
70
+ @indexes ||= Index::ClientModule.new(self)
65
71
  end
66
72
 
67
73
  # @return [Key::ClientModule]
@@ -69,6 +75,12 @@ module Sequence
69
75
  @keys ||= Key::ClientModule.new(self)
70
76
  end
71
77
 
78
+ # @private
79
+ # @return [Stats::ClientModule]
80
+ def stats
81
+ @stats ||= Stats::ClientModule.new(self)
82
+ end
83
+
72
84
  # @return [Token::ClientModule]
73
85
  def tokens
74
86
  @tokens ||= Token::ClientModule.new(self)
@@ -79,26 +91,9 @@ module Sequence
79
91
  @transactions ||= Transaction::ClientModule.new(self)
80
92
  end
81
93
 
82
- # @return [Feed::ClientModule]
83
- def feeds
84
- @feeds ||= Feed::ClientModule.new(self)
85
- end
86
-
87
- # @private
88
- # @return [Stats::ClientModule]
89
- def stats
90
- @stats ||= Stats::ClientModule.new(self)
91
- end
92
-
93
94
  # @return [DevUtils::ClientModule]
94
95
  def dev_utils
95
96
  @dev_utils ||= DevUtils::ClientModule.new(self)
96
97
  end
97
-
98
- private
99
-
100
- def team_name(api)
101
- api.post(SecureRandom.hex(10), '/hello', {})[:parsed_body]['team_name']
102
- end
103
98
  end
104
99
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequence
4
+ # @private
5
+ class Hello
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def call
11
+ b = @api.post(SecureRandom.hex(10), '/hello', {})[:parsed_body]
12
+ [b['team_name'], b['addr'], b['addr_ttl_seconds'].to_i]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './client_module'
4
+ require_relative './session'
5
+ require_relative './query'
6
+ require_relative './response_object'
7
+
8
+ module Sequence
9
+ # Indexes are used to precompute queries that could
10
+ # potentially be slow. When an application submits a
11
+ # query where the filter and group-by params match
12
+ # one of the defined indexes, the results can be
13
+ # returned from quickly from precomputed storage.
14
+ class Index < ResponseObject
15
+ # @!attribute [r] id
16
+ # Unique identifier of the index
17
+ # @return [String]
18
+ attrib :id
19
+
20
+ # @!attribute [r] type
21
+ # Type of index, "action" or "token".
22
+ # @return [String]
23
+ attrib :type
24
+
25
+ # @!attribute [r] filter
26
+ # The query filter used to select matching items.
27
+ # @return [String]
28
+ attrib :filter
29
+
30
+ # @!attribute [r] group_by
31
+ # Token/Action object fields to group by.
32
+ # @return [String]
33
+ attrib :group_by
34
+
35
+ class ClientModule < Sequence::ClientModule
36
+ # Create an index.
37
+ # @param id [String]
38
+ # Unique identifier. Auto-generated if not specified.
39
+ # @return [Index]
40
+ def create(id: nil, type:, filter:, group_by: [])
41
+ Index.new(client.session.request(
42
+ 'create-index',
43
+ id: id,
44
+ type: type,
45
+ filter: filter,
46
+ group_by: group_by,
47
+ ))
48
+ end
49
+
50
+ # Delete index by id.
51
+ # @option id [String] The unique ID of an index.
52
+ # @return [void]
53
+ def delete(id:)
54
+ client.session.request('delete-index', id: id)
55
+ nil
56
+ end
57
+
58
+ # List all indexes.
59
+ # Executes a query, returning an enumerable over individual indexes.
60
+ # @return [Query]
61
+ def list
62
+ Query.new(client)
63
+ end
64
+ end
65
+
66
+ class Query < Sequence::Query
67
+ def fetch(query)
68
+ client.session.request('list-indexes', query)
69
+ end
70
+
71
+ def translate(obj)
72
+ Index.new(obj)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -5,6 +5,7 @@ require 'json'
5
5
  require_relative './http_wrapper'
6
6
  require_relative './errors'
7
7
  require_relative './version'
8
+ require_relative './hello'
8
9
 
9
10
  module Sequence
10
11
  # @private
@@ -19,11 +20,11 @@ module Sequence
19
20
  ArgumentError,
20
21
  'missing credential',
21
22
  )
22
- @team_name = @opts[:team_name] || raise(
23
- ArgumentError,
24
- 'missing team_name',
25
- )
26
- @ledger_api = HttpWrapper.new('https://' + @opts[:addr], @credential, @opts)
23
+
24
+ @lock = Mutex.new # protects the following instance variables
25
+ @team_name, @addr, ttl_seconds = hello.call
26
+ @api = api(@addr)
27
+ @deadline = now + ttl_seconds
27
28
  end
28
29
 
29
30
  def dup
@@ -36,7 +37,20 @@ module Sequence
36
37
 
37
38
  def request_full_resp(id, path, body = {})
38
39
  id ||= SecureRandom.hex(10)
39
- @ledger_api.post(id, ledger_url(path), body) do |response|
40
+ deadline = nil
41
+ api = nil
42
+
43
+ @lock.synchronize do
44
+ deadline = @deadline
45
+ api = @api
46
+ path = "/#{@team_name}/#{@ledger}/#{path}".gsub('//', '/')
47
+ end
48
+
49
+ if now >= deadline
50
+ refresh
51
+ end
52
+
53
+ api.post(id, path, body) do |response|
40
54
  # require that the response contains the Chain-Request-ID
41
55
  # http header. Since the Sequence API will always set this
42
56
  # header, its absence indicates that the request stopped at
@@ -52,9 +66,44 @@ module Sequence
52
66
 
53
67
  private
54
68
 
55
- def ledger_url(path)
56
- path = path[1..-1] if path.start_with?('/')
57
- "/#{@team_name}/#{@ledger}/#{path}"
69
+ def refresh
70
+ Thread.new do
71
+ # extend the deadline long enough to get a fresh addr
72
+ @lock.synchronize do
73
+ @deadline = now + HttpWrapper::RETRY_TIMEOUT_SECS
74
+ end
75
+
76
+ begin
77
+ new_team_name, new_addr, ttl_seconds = hello.call
78
+ rescue StandardError # rubocop:disable Lint/HandleExceptions
79
+ # use existing values while trying for a successful /hello
80
+ else
81
+ @lock.synchronize do
82
+ @deadline = now + ttl_seconds
83
+
84
+ # unless addr changed, use existing API client
85
+ # in order to re-use the TLS connection
86
+ if @addr != new_addr
87
+ @addr = new_addr
88
+ @api = api(new_addr)
89
+ end
90
+
91
+ @team_name = new_team_name
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ def now
98
+ Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i
99
+ end
100
+
101
+ def hello
102
+ Sequence::Hello.new(api(ENV['SEQADDR'] || 'api.seq.com'))
103
+ end
104
+
105
+ def api(addr)
106
+ HttpWrapper.new('https://' + addr, @credential, @opts)
58
107
  end
59
108
  end
60
109
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sequence
4
- VERSION = '2.1'
4
+ VERSION = '2.2.rc.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequence-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.1'
4
+ version: 2.2.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chain Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-16 00:00:00.000000000 Z
11
+ date: 2018-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,20 +86,6 @@ dependencies:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: 0.14.1
89
- - !ruby/object:Gem::Dependency
90
- name: webmock
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: 2.3.2
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: 2.3.2
103
89
  - !ruby/object:Gem::Dependency
104
90
  name: yard
105
91
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +123,9 @@ files:
137
123
  - lib/sequence/errors.rb
138
124
  - lib/sequence/feed.rb
139
125
  - lib/sequence/flavor.rb
126
+ - lib/sequence/hello.rb
140
127
  - lib/sequence/http_wrapper.rb
128
+ - lib/sequence/index.rb
141
129
  - lib/sequence/key.rb
142
130
  - lib/sequence/page.rb
143
131
  - lib/sequence/query.rb
@@ -162,9 +150,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
162
150
  version: '2.3'
163
151
  required_rubygems_version: !ruby/object:Gem::Requirement
164
152
  requirements:
165
- - - ">="
153
+ - - ">"
166
154
  - !ruby/object:Gem::Version
167
- version: '0'
155
+ version: 1.3.1
168
156
  requirements: []
169
157
  rubyforge_project:
170
158
  rubygems_version: 2.7.6