proc 0.1.2 → 0.6.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: 2950f8e2178a95a40c29372c902203d883bda75ac84785a3579134b9394d7a52
4
- data.tar.gz: 6c8433c3f49bbc0a6a62187c9b992fd7c39e6eac2894f7d71a2056205bdc7900
3
+ metadata.gz: 1759094e21f61007e2f96393615f5ae03880bff36f6ee764e1072ba7b73bd310
4
+ data.tar.gz: 7495016b1b5e9de6e4d8a8c92dce90b4769f6404488d92b69f88ab06238ee6cb
5
5
  SHA512:
6
- metadata.gz: 36828988724d7e3cad08a3a741f576bfa50f8d53a459062892bb270e01da1d8a1ddf4977255976a314a15b4e79e8266da4089c9cdbb8f723c30d681099654c7f
7
- data.tar.gz: e224df7dcabcf284d5cf72f410be3ccf713dfbb0ff386ae5a50597e5c9a6b07634c87759f30d5e4b4a95fc0091d0c2f0aa490146a02b8806a3784033025fd123
6
+ metadata.gz: '00008d07672ae0a0aed43d4146b0c6ea687071d939085e19cc7ae82aabc770e33dcb959d53ec69705784c667ffdad75545650e97872870ccd1396285b034149c'
7
+ data.tar.gz: b7d89543b58a65bdd9522bf360c2a76132f2a7a391717af3d1f0fb665e49b0157b85081cfcd0ddacb289e82c5cb87036946da10944b16645550e03aa72329a1b
data/lib/proc.rb CHANGED
@@ -6,4 +6,12 @@ class Proc
6
6
  def self.connect(authorization, **options)
7
7
  Client.new(authorization, **options)
8
8
  end
9
+
10
+ def self.undefined
11
+ @_undefined ||= Object.new
12
+ end
13
+
14
+ def self.undefined?(value)
15
+ value == undefined
16
+ end
9
17
  end
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
@@ -4,8 +4,8 @@ class Proc
4
4
  class Callable
5
5
  attr_reader :proc, :input, :arguments
6
6
 
7
- def initialize(proc, client:, input: nil, arguments: {})
8
- @proc = proc
7
+ def initialize(proc, client:, input: Proc.undefined, arguments: {})
8
+ @proc = proc.to_s
9
9
  @client = client
10
10
  @input = input
11
11
  @arguments = arguments
@@ -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)
@@ -44,12 +44,15 @@ class Proc
44
44
  end
45
45
 
46
46
  def serialize
47
- {
48
- "{}" => {
49
- "<<" => serialized_input,
50
- "[]" => [[@proc, serialized_arguments]]
51
- }
52
- }
47
+ serialized = ["()", @proc]
48
+
49
+ unless Proc.undefined?(@input)
50
+ serialized << [">>", serialized_input]
51
+ end
52
+
53
+ serialized.concat(serialized_arguments)
54
+
55
+ ["{}", serialized]
53
56
  end
54
57
 
55
58
  def serialized_input
@@ -57,8 +60,8 @@ class Proc
57
60
  end
58
61
 
59
62
  def serialized_arguments
60
- @arguments.each_pair.each_with_object({}) { |(key, value), hash|
61
- hash[key.to_s] = serialize_value(value)
63
+ @arguments.map { |key, value|
64
+ ["$$", key.to_s, serialize_value(value)]
62
65
  }
63
66
  end
64
67
 
@@ -98,7 +101,7 @@ class Proc
98
101
  if value.respond_to?(:serialize)
99
102
  value.serialize
100
103
  else
101
- value
104
+ ["%%", value]
102
105
  end
103
106
  end
104
107
  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,64 +70,59 @@ 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 = { "<<" => serialize_value(input) }
75
-
76
- arguments.each_pair do |key, value|
77
- body[key.to_s] = serialize_value(value)
78
- end
79
-
80
- headers = {
81
- "authorization" => "bearer #{@authorization}"
82
- }.merge(DEFAULT_HEADERS)
77
+ def call(proc = nil, input = Proc.undefined, **arguments)
78
+ body = []
83
79
 
84
- begin
85
- response = super(:post, build_uri(proc), headers: headers, body: Oj.dump(body, mode: :custom), task: task)
86
-
87
- @remaining = response.headers["x-rate-limit-remaining"].to_s.to_i
88
- @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
89
83
 
90
- payload = Oj.load(response.read, mode: :compat)
91
- rescue => error
92
- # TODO: This should wrap `error`.
93
- #
94
- raise Proc::Unavailable, error.message
95
- ensure
96
- response&.close
97
- end
84
+ arguments.each_pair do |key, value|
85
+ body << ["$$", key.to_s, serialize_value(value)]
86
+ end
98
87
 
99
- case response.status
100
- when 200
101
- payload[">>"]
102
- when 400
103
- raise Proc::Invalid, payload.dig("error", "message")
104
- when 401
105
- raise Proc::Unauthorized, payload.dig("error", "message")
106
- when 403
107
- raise Proc::Forbidden, payload.dig("error", "message")
108
- when 404
109
- raise Proc::Undefined, payload.dig("error", "message")
110
- when 408
111
- raise Proc::Timeout, payload.dig("error", "message")
112
- when 429
113
- raise Proc::Limited, payload.dig("error", "message")
114
- when 500
115
- raise Proc::Error, payload.dig("error", "message")
116
- when 508
117
- raise Proc::Error, payload.dig("error", "message")
118
- else
119
- raise Proc::Error, "unhandled"
120
- end
121
- }.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
122
118
  end
123
119
 
124
- def method_missing(name, input = nil, **arguments)
125
- Callable.new(name, client: self, input: input, arguments: arguments)
120
+ def method_missing(name, input = input_omitted = true, *, **arguments)
121
+ if input_omitted
122
+ Callable.new(name, client: self, arguments: arguments)
123
+ else
124
+ Callable.new(name, client: self, input: input, arguments: arguments)
125
+ end
126
126
  end
127
127
 
128
128
  def respond_to_missing?(name, *)
@@ -134,6 +134,10 @@ class Proc
134
134
  end
135
135
  alias_method :arg, :argument
136
136
 
137
+ def close
138
+ @internal.close
139
+ end
140
+
137
141
  private def build_uri(proc)
138
142
  host_and_path = File.join(@host, proc.to_s.split(".").join("/"))
139
143
 
@@ -144,8 +148,44 @@ class Proc
144
148
  if value.respond_to?(:serialize)
145
149
  value.serialize
146
150
  else
147
- 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
148
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")
149
189
  end
150
190
  end
151
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)
@@ -37,33 +37,38 @@ class Proc
37
37
 
38
38
  def >>(other)
39
39
  composed = dup
40
-
41
- case other
42
- when Composition
43
- composed.merge(other)
44
- when Callable
45
- composed << other
46
- end
47
-
40
+ composed << other
48
41
  composed
49
42
  end
50
43
 
51
44
  def <<(callable)
52
- @callables << callable
45
+ case callable
46
+ when Composition
47
+ merge(callable)
48
+ when Callable
49
+ @callables << callable
50
+ end
53
51
  end
54
52
 
55
53
  def serialize
56
- {
57
- "{}" => {
58
- "<<" => serialized_input,
59
- "[]" => serialized_calls
60
- }.merge(serialized_arguments)
61
- }
54
+ serialized = ["{}"]
55
+
56
+ unless Proc.undefined?(@input)
57
+ serialized << [">>", serialized_input]
58
+ end
59
+
60
+ serialized + serialized_arguments + serialized_calls
62
61
  end
63
62
 
64
63
  def serialized_calls
65
64
  @callables.map { |callable|
66
- [callable.proc, callable.serialized_arguments]
65
+ serialized = ["()", callable.proc]
66
+
67
+ unless Proc.undefined?(callable.input)
68
+ serialized << [">>", callable.serialized_input]
69
+ end
70
+
71
+ serialized.concat(callable.serialized_arguments)
67
72
  }
68
73
  end
69
74
 
@@ -72,8 +77,8 @@ class Proc
72
77
  end
73
78
 
74
79
  def serialized_arguments
75
- @arguments.each_pair.each_with_object({}) { |(key, value), hash|
76
- hash[key.to_s] = serialize_value(value)
80
+ @arguments.map { |key, value|
81
+ ["$$", key.to_s, serialize_value(value)]
77
82
  }
78
83
  end
79
84
 
@@ -88,7 +93,7 @@ class Proc
88
93
  if value.respond_to?(:serialize)
89
94
  value.serialize
90
95
  else
91
- value
96
+ ["%%", value]
92
97
  end
93
98
  end
94
99
  end
@@ -5,50 +5,45 @@ require "async/http/internet"
5
5
 
6
6
  require "protocol/http/body/streamable"
7
7
 
8
+ require "core/async"
9
+
8
10
  require_relative "request"
9
11
  require_relative "response"
10
12
 
11
- require_relative "../null_logger"
12
-
13
13
  class Proc
14
14
  module Http
15
15
  class Client
16
+ include Is::Async
17
+
16
18
  def initialize
17
19
  @internet = Async::HTTP::Internet.new
18
- @responses = {}
19
20
  end
20
21
 
21
- def call(method, uri, params: {}, headers: {}, body: nil, task: nil)
22
+ def call(method, uri, params: {}, headers: {}, body: nil)
22
23
  request = Request.new(method: method, uri: uri, params: params, headers: headers, body: body)
23
24
 
24
- if task
25
- make_request(request)
26
- else
27
- Async(logger: NullLogger) {
28
- make_request(request)
29
- }.wait
30
- end
25
+ await {
26
+ begin
27
+ response = make_request(request)
28
+
29
+ yield response
30
+ ensure
31
+ response&.close
32
+ end
33
+ }
31
34
  end
32
35
 
33
36
  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
37
  @internet.close
39
38
  end
40
39
 
41
- def count
42
- @responses.count
43
- end
44
-
45
40
  private def make_request(request)
46
41
  async_response = @internet.call(*request.callable)
47
42
  wrap_async_response_for_request(async_response, request)
48
43
  end
49
44
 
50
45
  private def wrap_async_response_for_request(async_response, request)
51
- @responses[async_response] = Response.new(request, async_response)
46
+ Response.new(request, async_response)
52
47
  end
53
48
  end
54
49
  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.1.2"
4
+ VERSION = "0.6.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.1.2
4
+ version: 0.6.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-10-31 00:00:00.000000000 Z
11
+ date: 2021-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.52.5
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.0.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.0.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: oj
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -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.1.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