proc 0.1.2 → 0.6.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: 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