proc 0.2.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75ef8a4c8d8b8f07682996ca70c0263f5e0b6d123493137a07f92717c9c16eab
4
- data.tar.gz: 48d2b0b5a4e453366ec4fc99536f98d875f804cb705ff5fde9a8b4b2d46e74c0
3
+ metadata.gz: 3436b4fd5fc66c40110f6dbf9cae15ab41d3e056126efd0aeb2ea1f3d9a0dd17
4
+ data.tar.gz: 1e4d324315a902f1f53ad611f8379cc6a3ec86f7c897c0dd27cf8901736c85ce
5
5
  SHA512:
6
- metadata.gz: 1fca54bd564be4fa0ac560ee4c81c9f6d81421b6fe26a6a7038ac97c4b2a17da34359949ba9d1d02191370022d916727793bda08e3d5a3c6d50d577acfaea17b
7
- data.tar.gz: 7a7bba01f304f8866ff2cd69b779c4a4995b966d0ec835d78da29f577704c89d848d79b83b516c5b53df59c0352fb7a038f4f28e2a2d02fab5337048cbfb6fff
6
+ metadata.gz: ac68f3119ab651efe8705ebe7cc68ad33e7cf9b49c58248c390f5667e31f7521b2b8494f169e213aae4a1a4371df45c6d485b04af743ddb872c993ed04c0dd2b
7
+ data.tar.gz: cc114dca8b977b3b365127120ad0f1ae37b53e0e75e5f2a025d9bc0741ebdc5f9fb667be6fd4df2793eab0fd9c02ea5b902146f995624d832f91642d2a4064cc
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
@@ -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)
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,16 @@ require "oj"
6
6
  require_relative "argument"
7
7
  require_relative "callable"
8
8
  require_relative "composition"
9
- require_relative "null_logger"
10
9
 
11
10
  require_relative "http/client"
12
11
 
12
+ Console.logger.off!
13
+
14
+ Oj.default_options = {
15
+ mode: :custom,
16
+ bigdecimal_load: :auto
17
+ }.freeze
18
+
13
19
  class Proc
14
20
  class Error < StandardError
15
21
  end
@@ -35,13 +41,12 @@ class Proc
35
41
  class Timeout < Error
36
42
  end
37
43
 
38
- class Client < Http::Client
44
+ class Client
39
45
  def initialize(authorization, scheme: "https", host: "proc.dev")
40
46
  @authorization = authorization
41
47
  @scheme = scheme
42
48
  @host = host
43
-
44
- super()
49
+ @internal = Http::Client.new
45
50
  end
46
51
 
47
52
  def [](proc)
@@ -65,65 +70,54 @@ class Proc
65
70
  end
66
71
 
67
72
  DEFAULT_HEADERS = {
68
- "accept" => "application/json",
69
- "content-type" => "application/json"
73
+ "accept" => "application/vnd.proc+json",
74
+ "content-type" => "application/vnd.proc+json"
70
75
  }.freeze
71
76
 
72
- def call(proc = nil, input = nil, **arguments)
73
- Async(logger: NullLogger) { |task|
74
- body = {}
75
-
76
- unless Proc.undefined?(input)
77
- body["<<"] = serialize_value(input)
78
- end
79
-
80
- arguments.each_pair do |key, value|
81
- body[key.to_s] = serialize_value(value)
82
- end
83
-
84
- headers = {
85
- "authorization" => "bearer #{@authorization}"
86
- }.merge(DEFAULT_HEADERS)
77
+ def call(proc = nil, input = Proc.undefined, **arguments)
78
+ body = []
87
79
 
88
- begin
89
- response = super(:post, build_uri(proc), headers: headers, body: Oj.dump(body, mode: :custom), task: task)
90
-
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)
80
+ unless Proc.undefined?(input)
81
+ body << [">>", serialize_value(input)]
82
+ end
93
83
 
94
- payload = Oj.load(response.read, mode: :compat)
95
- rescue
96
- raise Proc::Unavailable
97
- ensure
98
- response&.close
99
- end
84
+ arguments.each_pair do |key, value|
85
+ body << ["$$", key.to_s, serialize_value(value)]
86
+ end
100
87
 
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")
120
- else
121
- raise Proc::Error, "unhandled"
122
- end
123
- }.wait
88
+ headers = {
89
+ "authorization" => "bearer #{@authorization}"
90
+ }.merge(DEFAULT_HEADERS)
91
+
92
+ status, payload = get_payload(proc: proc, headers: headers, body: body)
93
+
94
+ case status
95
+ when 200
96
+ extract_output(payload)
97
+ when 400
98
+ raise Proc::Invalid, extract_error_message(payload)
99
+ when 401
100
+ raise Proc::Unauthorized, extract_error_message(payload)
101
+ when 403
102
+ raise Proc::Forbidden, extract_error_message(payload)
103
+ when 404
104
+ raise Proc::Undefined, extract_error_message(payload)
105
+ when 408
106
+ raise Proc::Timeout, extract_error_message(payload)
107
+ when 413
108
+ raise Proc::Invalid, extract_error_message(payload)
109
+ when 429
110
+ raise Proc::Limited, extract_error_message(payload)
111
+ when 500
112
+ raise Proc::Error, extract_error_message(payload)
113
+ when 508
114
+ raise Proc::Error, extract_error_message(payload)
115
+ else
116
+ raise Proc::Error, "unhandled"
117
+ end
124
118
  end
125
119
 
126
- def method_missing(name, input = input_omitted = true, **arguments)
120
+ def method_missing(name, input = input_omitted = true, *, **arguments)
127
121
  if input_omitted
128
122
  Callable.new(name, client: self, arguments: arguments)
129
123
  else
@@ -140,6 +134,10 @@ class Proc
140
134
  end
141
135
  alias_method :arg, :argument
142
136
 
137
+ def close
138
+ @internal.close
139
+ end
140
+
143
141
  private def build_uri(proc)
144
142
  host_and_path = File.join(@host, proc.to_s.split(".").join("/"))
145
143
 
@@ -150,8 +148,44 @@ class Proc
150
148
  if value.respond_to?(:serialize)
151
149
  value.serialize
152
150
  else
153
- value
151
+ ["%%", value]
152
+ end
153
+ end
154
+
155
+ private def get_payload(proc:, headers:, body:)
156
+ @internal.call(:post, build_uri(proc), headers: headers, body: Oj.dump(body)) do |response|
157
+ @remaining = response.headers["x-rate-limit-remaining"].to_s.to_i
158
+ @resets_at = Time.at(response.headers["x-rate-limit-reset"].to_s.to_i)
159
+ [response.status, Oj.load(response.read)]
160
+ end
161
+ rescue
162
+ raise Proc::Unavailable
163
+ end
164
+
165
+ private def extract_output(payload)
166
+ payload.each do |tuple|
167
+ case tuple[0]
168
+ when "<<"
169
+ return tuple[1]
170
+ end
154
171
  end
172
+
173
+ nil
174
+ end
175
+
176
+ private def extract_error(payload)
177
+ payload.each do |tuple|
178
+ case tuple[0]
179
+ when "!!"
180
+ return tuple[1]
181
+ end
182
+ end
183
+
184
+ nil
185
+ end
186
+
187
+ private def extract_error_message(payload)
188
+ extract_error(payload)&.dig("message")
155
189
  end
156
190
  end
157
191
  end
@@ -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)
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
@@ -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.2.0"
4
+ VERSION = "0.7.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.2.0
4
+ version: 0.7.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-08 00:00:00.000000000 Z
11
+ date: 2021-02-16 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: []
@@ -54,7 +68,6 @@ files:
54
68
  - lib/proc/http/client.rb
55
69
  - lib/proc/http/request.rb
56
70
  - lib/proc/http/response.rb
57
- - lib/proc/null_logger.rb
58
71
  - lib/proc/version.rb
59
72
  homepage: https://proc.dev/
60
73
  licenses:
@@ -75,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
88
  - !ruby/object:Gem::Version
76
89
  version: '0'
77
90
  requirements: []
78
- rubygems_version: 3.1.2
91
+ rubygems_version: 3.2.4
79
92
  signing_key:
80
93
  specification_version: 4
81
94
  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