proc 0.3.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3a73eafa61306bca405c0eaec0f8df0d145b22d27a98ee8dcf28db94cdadfa3
4
- data.tar.gz: b1e95096528fe529ec664a370095269ae26672994178ed62e3c78159c46ed173
3
+ metadata.gz: ece2d4c0f8e4e0aa122ca1df9e751d061afaa802dc056e5dd2c0ba7b272ff3e8
4
+ data.tar.gz: 4f9ce5d28d966c23097dd3445d5ea5fc37fe9d0ecea1c5b13771b9633ac28d0c
5
5
  SHA512:
6
- metadata.gz: 9708b1585d8c95deb6016cc5dbed10d5c7bffdfa55421d0392d3c51ec2af5ce334eb5b41283c585795874c7cdf5b035e6eb41ca145ee56d7409147546b61a6bf
7
- data.tar.gz: ec138355afed48dde883579c73d304196b3cb2b6b8ac7d5a0986b43c5bffb6591fd33c019b516807c46b2c1ef3c6d75df7fc10d5bae10ecfbc38428ea89977c9
6
+ metadata.gz: c084f766e97cced8633a74379d700d06efa54bc6f0eb81cf6351af9e2528aea465ebff4dc4d3dd3631c20016ce70a1a36c2245607fe14f85aaa29d115d3ac9a5
7
+ data.tar.gz: 62303f9d27683c07bc0ff8f5df8c8697a669fa8df7ac496929457e3e572384ded1c779580ddf09082d830b8658c6c1be07eadb3478255de9b013e318a51b2755
data/lib/proc.rb CHANGED
@@ -8,7 +8,7 @@ class Proc
8
8
  end
9
9
 
10
10
  def self.undefined
11
- @_undefined ||= Object.new
11
+ @_undefined ||= ::Object.new
12
12
  end
13
13
 
14
14
  def self.undefined?(value)
data/lib/proc/argument.rb CHANGED
@@ -8,7 +8,7 @@ class Proc
8
8
  end
9
9
 
10
10
  def serialize
11
- {"::" => {"name" => @name.to_s}.merge(serialized_options)}
11
+ ["@@", @name.to_s, serialized_options]
12
12
  end
13
13
 
14
14
  def serialized_options
@@ -21,7 +21,7 @@ class Proc
21
21
  if value.respond_to?(:serialize)
22
22
  value.serialize
23
23
  else
24
- value
24
+ ["%%", value]
25
25
  end
26
26
  end
27
27
  end
data/lib/proc/callable.rb CHANGED
@@ -16,7 +16,7 @@ class Proc
16
16
  @arguments = arguments.dup
17
17
  end
18
18
 
19
- def call(input = input_omitted = true, **arguments)
19
+ def call(input = input_omitted = true, **arguments, &block)
20
20
  callable = self.class.new(
21
21
  @proc,
22
22
  client: @client,
@@ -24,7 +24,7 @@ class Proc
24
24
  arguments: @arguments.merge(arguments)
25
25
  )
26
26
 
27
- @client.call(@proc, callable.serialized_input, **callable.serialized_arguments)
27
+ @client.call(@proc, callable.input, **callable.arguments, &block)
28
28
  end
29
29
 
30
30
  def with(input = input_omitted = true, **arguments)
@@ -43,14 +43,20 @@ class Proc
43
43
  composed
44
44
  end
45
45
 
46
- def serialize
47
- wrapped = {"[]" => [[@proc, serialized_arguments]]}
46
+ def serialize(unwrapped: false)
47
+ serialized = ["()", @proc]
48
48
 
49
49
  unless Proc.undefined?(@input)
50
- wrapped["<<"] = serialized_input
50
+ serialized << [">>", serialized_input]
51
51
  end
52
52
 
53
- {"{}" => wrapped}
53
+ serialized.concat(serialized_arguments)
54
+
55
+ if unwrapped
56
+ serialized
57
+ else
58
+ ["{}", serialized]
59
+ end
54
60
  end
55
61
 
56
62
  def serialized_input
@@ -58,8 +64,8 @@ class Proc
58
64
  end
59
65
 
60
66
  def serialized_arguments
61
- @arguments.each_pair.each_with_object({}) { |(key, value), hash|
62
- hash[key.to_s] = serialize_value(value)
67
+ @arguments.map { |key, value|
68
+ ["$$", key.to_s, serialize_value(value)]
63
69
  }
64
70
  end
65
71
 
@@ -99,7 +105,7 @@ class Proc
99
105
  if value.respond_to?(:serialize)
100
106
  value.serialize
101
107
  else
102
- value
108
+ ["%%", value]
103
109
  end
104
110
  end
105
111
  end
data/lib/proc/client.rb CHANGED
@@ -6,10 +6,19 @@ require "oj"
6
6
  require_relative "argument"
7
7
  require_relative "callable"
8
8
  require_relative "composition"
9
- require_relative "null_logger"
9
+ require_relative "enumerator"
10
10
 
11
11
  require_relative "http/client"
12
12
 
13
+ Console.logger.off!
14
+
15
+ Oj.default_options = {
16
+ mode: :custom,
17
+ bigdecimal_load: :auto,
18
+ float_precision: 0,
19
+ second_precision: 6
20
+ }.freeze
21
+
13
22
  class Proc
14
23
  class Error < StandardError
15
24
  end
@@ -35,13 +44,14 @@ class Proc
35
44
  class Timeout < Error
36
45
  end
37
46
 
38
- class Client < Http::Client
47
+ class Client
48
+ attr_reader :authorization, :scheme, :host
49
+
39
50
  def initialize(authorization, scheme: "https", host: "proc.dev")
40
51
  @authorization = authorization
41
52
  @scheme = scheme
42
53
  @host = host
43
-
44
- super()
54
+ @internal = Http::Client.new
45
55
  end
46
56
 
47
57
  def [](proc)
@@ -65,65 +75,69 @@ class Proc
65
75
  end
66
76
 
67
77
  DEFAULT_HEADERS = {
68
- "accept" => "application/json",
69
- "content-type" => "application/json"
78
+ "accept" => "application/vnd.proc+json",
79
+ "content-type" => "application/vnd.proc+json"
70
80
  }.freeze
71
81
 
72
- def call(proc = nil, input = nil, **arguments)
73
- Async(logger: NullLogger) { |task|
74
- body = {"<>" => true}
82
+ def call(proc = nil, input = Proc.undefined, **arguments, &block)
83
+ body = []
75
84
 
76
- unless Proc.undefined?(input)
77
- body["<<"] = serialize_value(input)
78
- end
85
+ unless Proc.undefined?(input)
86
+ body << [">>", serialize_value(input)]
87
+ end
79
88
 
80
- arguments.each_pair do |key, value|
81
- body[key.to_s] = serialize_value(value)
82
- end
89
+ arguments.each_pair do |key, value|
90
+ body << ["$$", key.to_s, serialize_value(value)]
91
+ end
83
92
 
84
- headers = {
85
- "authorization" => "bearer #{@authorization}"
86
- }.merge(DEFAULT_HEADERS)
93
+ headers = {
94
+ "authorization" => "bearer #{@authorization}"
95
+ }.merge(DEFAULT_HEADERS)
87
96
 
88
- begin
89
- response = super(:post, build_uri(proc), headers: headers, body: Oj.dump(body, mode: :custom), task: task)
97
+ status, headers, payload = get_payload(proc: proc, headers: headers, body: body)
90
98
 
91
- @remaining = response.headers["x-rate-limit-remaining"].to_s.to_i
92
- @resets_at = Time.at(response.headers["x-rate-limit-reset"].to_s.to_i)
99
+ case status
100
+ when 200
101
+ result = extract_output(payload)
93
102
 
94
- payload = Oj.load(response.read, mode: :compat)
95
- rescue
96
- raise Proc::Unavailable
97
- ensure
98
- response&.close
99
- end
103
+ if (cursor = headers["x-cursor"])
104
+ enumerator = Enumerator.new(result) {
105
+ arguments[:cursor] = cursor.to_s
106
+ call(proc, input, **arguments)
107
+ }
100
108
 
101
- case response.status
102
- when 200
103
- payload[">>"]
104
- when 400
105
- raise Proc::Invalid, payload.dig("error", "message")
106
- when 401
107
- raise Proc::Unauthorized, payload.dig("error", "message")
108
- when 403
109
- raise Proc::Forbidden, payload.dig("error", "message")
110
- when 404
111
- raise Proc::Undefined, payload.dig("error", "message")
112
- when 408
113
- raise Proc::Timeout, payload.dig("error", "message")
114
- when 429
115
- raise Proc::Limited, payload.dig("error", "message")
116
- when 500
117
- raise Proc::Error, payload.dig("error", "message")
118
- when 508
119
- raise Proc::Error, payload.dig("error", "message")
109
+ if block
110
+ enumerator.each(&block)
111
+ else
112
+ enumerator
113
+ end
120
114
  else
121
- raise Proc::Error, "unhandled"
115
+ result
122
116
  end
123
- }.wait
117
+ when 400
118
+ raise Proc::Invalid, extract_error_message(payload)
119
+ when 401
120
+ raise Proc::Unauthorized, extract_error_message(payload)
121
+ when 403
122
+ raise Proc::Forbidden, extract_error_message(payload)
123
+ when 404
124
+ raise Proc::Undefined, extract_error_message(payload)
125
+ when 408
126
+ raise Proc::Timeout, extract_error_message(payload)
127
+ when 413
128
+ raise Proc::Invalid, extract_error_message(payload)
129
+ when 429
130
+ raise Proc::Limited, extract_error_message(payload)
131
+ when 500
132
+ raise Proc::Error, extract_error_message(payload)
133
+ when 508
134
+ raise Proc::Error, extract_error_message(payload)
135
+ else
136
+ raise Proc::Error, "unhandled"
137
+ end
124
138
  end
125
139
 
126
- def method_missing(name, input = input_omitted = true, **arguments)
140
+ def method_missing(name, input = input_omitted = true, *, **arguments)
127
141
  if input_omitted
128
142
  Callable.new(name, client: self, arguments: arguments)
129
143
  else
@@ -140,6 +154,10 @@ class Proc
140
154
  end
141
155
  alias_method :arg, :argument
142
156
 
157
+ def close
158
+ @internal.close
159
+ end
160
+
143
161
  private def build_uri(proc)
144
162
  host_and_path = File.join(@host, proc.to_s.split(".").join("/"))
145
163
 
@@ -150,8 +168,44 @@ class Proc
150
168
  if value.respond_to?(:serialize)
151
169
  value.serialize
152
170
  else
153
- value
171
+ ["%%", value]
172
+ end
173
+ end
174
+
175
+ private def get_payload(proc:, headers:, body:)
176
+ @internal.call(:post, build_uri(proc), headers: headers, body: Oj.dump(body)) do |response|
177
+ @remaining = response.headers["x-rate-limit-remaining"].to_s.to_i
178
+ @resets_at = Time.at(response.headers["x-rate-limit-reset"].to_s.to_i)
179
+ [response.status, response.headers, Oj.load(response.read)]
180
+ end
181
+ rescue
182
+ raise Proc::Unavailable
183
+ end
184
+
185
+ private def extract_output(payload)
186
+ payload.each do |tuple|
187
+ case tuple[0]
188
+ when "<<"
189
+ return tuple[1]
190
+ end
191
+ end
192
+
193
+ nil
194
+ end
195
+
196
+ private def extract_error(payload)
197
+ payload.each do |tuple|
198
+ case tuple[0]
199
+ when "!!"
200
+ return tuple[1]
201
+ end
154
202
  end
203
+
204
+ nil
205
+ end
206
+
207
+ private def extract_error_message(payload)
208
+ extract_error(payload)&.dig("message")
155
209
  end
156
210
  end
157
211
  end
@@ -15,7 +15,7 @@ class Proc
15
15
  @callables = @callables.dup
16
16
  end
17
17
 
18
- def call(input = input_omitted = true, **arguments)
18
+ def call(input = input_omitted = true, **arguments, &block)
19
19
  callable = self.class.new(
20
20
  client: @client,
21
21
  input: input_omitted ? @input : input,
@@ -23,7 +23,7 @@ class Proc
23
23
  arguments: @arguments.merge(arguments)
24
24
  )
25
25
 
26
- @client.call("proc.exec", nil, proc: callable.serialize)
26
+ @client.call("exec", Proc.undefined, proc: callable, &block)
27
27
  end
28
28
 
29
29
  def with(input = input_omitted = true, **arguments)
@@ -51,25 +51,13 @@ class Proc
51
51
  end
52
52
 
53
53
  def serialize
54
- wrapped = {"[]" => serialized_calls}
54
+ serialized = ["{}"]
55
55
 
56
56
  unless Proc.undefined?(@input)
57
- wrapped["<<"] = serialized_input
57
+ serialized << [">>", serialized_input]
58
58
  end
59
59
 
60
- {"{}" => wrapped.merge(serialized_arguments)}
61
- end
62
-
63
- def serialized_calls
64
- @callables.map { |callable|
65
- arguments = callable.serialized_arguments
66
-
67
- unless Proc.undefined?(callable.input)
68
- arguments["<<"] = callable.serialized_input
69
- end
70
-
71
- [callable.proc, arguments]
72
- }
60
+ serialized + serialized_arguments + @callables.map { |callable| callable.serialize(unwrapped: true) }
73
61
  end
74
62
 
75
63
  def serialized_input
@@ -77,8 +65,8 @@ class Proc
77
65
  end
78
66
 
79
67
  def serialized_arguments
80
- @arguments.each_pair.each_with_object({}) { |(key, value), hash|
81
- hash[key.to_s] = serialize_value(value)
68
+ @arguments.map { |key, value|
69
+ ["$$", key.to_s, serialize_value(value)]
82
70
  }
83
71
  end
84
72
 
@@ -93,7 +81,7 @@ class Proc
93
81
  if value.respond_to?(:serialize)
94
82
  value.serialize
95
83
  else
96
- value
84
+ ["%%", value]
97
85
  end
98
86
  end
99
87
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Proc
4
+ class Enumerator
5
+ include Enumerable
6
+
7
+ def initialize(values, &next_block)
8
+ @values = values
9
+ @next_block = next_block
10
+ end
11
+
12
+ def each(&block)
13
+ return to_enum(:each) unless block
14
+
15
+ @values.each(&block)
16
+ @next_block.call.each(&block)
17
+ end
18
+ end
19
+ end
@@ -3,52 +3,39 @@
3
3
  require "async"
4
4
  require "async/http/internet"
5
5
 
6
- require "protocol/http/body/streamable"
6
+ require "core/async"
7
7
 
8
8
  require_relative "request"
9
9
  require_relative "response"
10
10
 
11
- require_relative "../null_logger"
12
-
13
11
  class Proc
14
12
  module Http
15
13
  class Client
16
- def initialize
17
- @internet = Async::HTTP::Internet.new
18
- @responses = {}
19
- end
14
+ include Is::Async
20
15
 
21
- def call(method, uri, params: {}, headers: {}, body: nil, task: nil)
16
+ def call(method, uri, params: {}, headers: {}, body: nil)
17
+ internet = Async::HTTP::Internet.new
22
18
  request = Request.new(method: method, uri: uri, params: params, headers: headers, body: body)
23
19
 
24
- if task
25
- make_request(request)
26
- else
27
- Async(logger: NullLogger) {
28
- make_request(request)
29
- }.wait
30
- end
31
- end
32
-
33
- def close
34
- # TODO: Make sure this works. We should also close / clear after accumulating some amount.
35
- #
36
- @responses.each_value(&:close)
37
- @responses.clear
38
- @internet.close
39
- end
20
+ await {
21
+ begin
22
+ response = make_request(internet, request)
40
23
 
41
- def count
42
- @responses.count
24
+ yield response
25
+ ensure
26
+ response&.close
27
+ internet&.close
28
+ end
29
+ }
43
30
  end
44
31
 
45
- private def make_request(request)
46
- async_response = @internet.call(*request.callable)
32
+ private def make_request(internet, request)
33
+ async_response = internet.call(*request.callable)
47
34
  wrap_async_response_for_request(async_response, request)
48
35
  end
49
36
 
50
37
  private def wrap_async_response_for_request(async_response, request)
51
- @responses[async_response] = Response.new(request, async_response)
38
+ Response.new(request, async_response)
52
39
  end
53
40
  end
54
41
  end
data/lib/proc/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Proc
4
- VERSION = "0.3.0"
4
+ VERSION = "0.8.0"
5
5
 
6
6
  def self.version
7
7
  VERSION
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Powell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-23 00:00:00.000000000 Z
11
+ date: 2021-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.52.5
19
+ version: 0.54.1
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.52.5
26
+ version: 0.54.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: core-async
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: oj
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '3.10'
47
+ version: '3.11'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '3.10'
54
+ version: '3.11'
41
55
  description: Proc client library.
42
56
  email: bryan@metabahn.com
43
57
  executables: []
@@ -51,10 +65,10 @@ files:
51
65
  - lib/proc/callable.rb
52
66
  - lib/proc/client.rb
53
67
  - lib/proc/composition.rb
68
+ - lib/proc/enumerator.rb
54
69
  - lib/proc/http/client.rb
55
70
  - lib/proc/http/request.rb
56
71
  - lib/proc/http/response.rb
57
- - lib/proc/null_logger.rb
58
72
  - lib/proc/version.rb
59
73
  homepage: https://proc.dev/
60
74
  licenses:
@@ -75,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
89
  - !ruby/object:Gem::Version
76
90
  version: '0'
77
91
  requirements: []
78
- rubygems_version: 3.1.4
92
+ rubygems_version: 3.2.4
79
93
  signing_key:
80
94
  specification_version: 4
81
95
  summary: Proc client library.
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Proc
4
- class NullLogger
5
- class << self
6
- def method_missing(*, **)
7
- end
8
-
9
- def respond_to_missing?(*)
10
- true
11
- end
12
- end
13
- end
14
- end