micro-rb 0.1.0.rc1 → 0.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -4
- data/README.md +34 -8
- data/lib/micro/{sidecar → clients}/base.rb +3 -3
- data/lib/micro/clients/http.rb +18 -0
- data/lib/micro/clients/rpc.rb +21 -0
- data/lib/micro/clients/sidecar.rb +24 -0
- data/lib/micro/configuration.rb +19 -3
- data/lib/micro/examples/fib.rb +47 -0
- data/lib/micro/examples/proto/fib.proto +13 -0
- data/lib/micro/examples/proto/fib_pb.rb +20 -0
- data/lib/micro/handler_manager.rb +9 -9
- data/lib/micro/proto/debug.proto +2 -0
- data/lib/micro/servers/web.rb +11 -21
- data/lib/micro/version.rb +1 -1
- data/lib/microrb.rb +4 -3
- metadata +9 -5
- data/lib/micro/sidecar/call.rb +0 -18
- data/lib/micro/sidecar/register.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4214b295604dcf084cac803a951262200ec128b
|
4
|
+
data.tar.gz: e345620800f3507ba539a95ed35c703fd0643229
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06afa4711aa6ea7414a3974c1f84a09dc31f325dd5e107cfefb702c5febbc054064e652ac6ca7acad8b3b117e9baa8326341f69fb5c40d5a64a4aa1d6b0d487f
|
7
|
+
data.tar.gz: 74063eab50bcd01092800c9003f6ee30bb53a657537b0607f18528dbf006708f1918791d79b1f595927b0f31c65c5c98245157056ae8f0d080d4931e3f2981c2
|
data/Gemfile
CHANGED
@@ -5,7 +5,6 @@ source 'https://rubygems.org'
|
|
5
5
|
# Specify your gem's dependencies in microrb.gemspec
|
6
6
|
gemspec
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
8
|
+
gem 'awesome_print'
|
9
|
+
gem 'puma'
|
10
|
+
gem 'rubocop', '~> 0.48.1', require: false
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[![Build Status](https://travis-ci.org/amedeiros/micro-rb.svg?branch=master)](https://travis-ci.org/amedeiros/micro-rb)
|
1
|
+
[![Build Status](https://travis-ci.org/amedeiros/micro-rb.svg?branch=master)](https://travis-ci.org/amedeiros/micro-rb) [![Gem Version](https://badge.fury.io/rb/micro-rb.svg)](https://badge.fury.io/rb/micro-rb)
|
2
2
|
|
3
3
|
# MicroRb
|
4
4
|
|
@@ -7,12 +7,6 @@ MicroRb uses the [sidecar](https://github.com/micro/micro/tree/master/car) that
|
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
10
|
-
Currently not on rubygems install with bundler and git
|
11
|
-
|
12
|
-
```ruby
|
13
|
-
gem 'micro-rb', github: 'amedeiros/micro-rb'
|
14
|
-
````
|
15
|
-
|
16
10
|
Add this line to your application's Gemfile:
|
17
11
|
|
18
12
|
```ruby
|
@@ -25,7 +19,7 @@ And then execute:
|
|
25
19
|
|
26
20
|
Or install it yourself as:
|
27
21
|
|
28
|
-
$ gem install micro-rb
|
22
|
+
$ gem install micro-rb -v '0.1.0.rc2'
|
29
23
|
|
30
24
|
## Status
|
31
25
|
|
@@ -87,6 +81,13 @@ Configuration has the following defaults for sidecar endpoint.
|
|
87
81
|
|
88
82
|
`Registy: "/registry"`
|
89
83
|
|
84
|
+
Configuration has the following defaults for api gateway.
|
85
|
+
|
86
|
+
`Host: http://127.0.0.1`
|
87
|
+
|
88
|
+
`Port: 3002`
|
89
|
+
|
90
|
+
`Rpc: "/rpc"`
|
90
91
|
|
91
92
|
Configuration can be changed.
|
92
93
|
|
@@ -95,6 +96,10 @@ MicroRb::Configuration.configure do |c|
|
|
95
96
|
c.sidecar_host = 'http://mysite.com'
|
96
97
|
c.sidecar_port = '8080'
|
97
98
|
c.sidecar_registry = '/awesome_registry'
|
99
|
+
|
100
|
+
c.gateway_host = 'http://mysite.com'
|
101
|
+
c.gateway_port = '8080'
|
102
|
+
c.gateway_rpc = '/awesome_micro_rb'
|
98
103
|
end
|
99
104
|
```
|
100
105
|
|
@@ -137,6 +142,14 @@ Date: Tue, 09 May 2017 17:50:47 GMT
|
|
137
142
|
}
|
138
143
|
```
|
139
144
|
|
145
|
+
```ruby
|
146
|
+
result = MicroRb::Clients::Rpc.call(service: 'test', method: 'MyHandler.sum', params: {a:1, b:2})
|
147
|
+
ap result
|
148
|
+
{
|
149
|
+
"total" => 3
|
150
|
+
}
|
151
|
+
```
|
152
|
+
|
140
153
|
## Calling the service directly
|
141
154
|
|
142
155
|
```
|
@@ -150,6 +163,19 @@ Server: WEBrick/1.3.1 (Ruby/2.4.0/2016-12-24)
|
|
150
163
|
{"result":{"total":3},"id":"1"}
|
151
164
|
```
|
152
165
|
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
result = MicroRb::Clients::Http.call(uri: 'http://0.0.0.0:3000', service: 'test', method: 'MyHandler.sum', params: {a:1, b:2})
|
169
|
+
ap result
|
170
|
+
|
171
|
+
{
|
172
|
+
"result" => {
|
173
|
+
"total" => 3
|
174
|
+
},
|
175
|
+
"id" => nil
|
176
|
+
}
|
177
|
+
```
|
178
|
+
|
153
179
|
## Project Generator
|
154
180
|
|
155
181
|
```
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require 'httparty'
|
5
5
|
|
6
6
|
module MicroRb
|
7
|
-
module
|
7
|
+
module Clients
|
8
8
|
module Base
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
@@ -17,8 +17,8 @@ module MicroRb
|
|
17
17
|
{ body: body.to_json, headers: { 'Content-Type' => CONTENT_TYPE } }
|
18
18
|
end
|
19
19
|
|
20
|
-
def self.
|
21
|
-
|
20
|
+
def self.decode(json)
|
21
|
+
MultiJson.decode(json)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module MicroRb
|
5
|
+
module Clients
|
6
|
+
class Http
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def self.call(uri:, service:, method:, params:, klass_response: nil)
|
10
|
+
response = decode(post(uri, options(service: service, method: method, params: Array.wrap(params))))
|
11
|
+
|
12
|
+
return klass_response.new(response.to_h.symbolize_keys!) if klass_response
|
13
|
+
|
14
|
+
response
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module MicroRb
|
5
|
+
module Clients
|
6
|
+
class Rpc
|
7
|
+
include Base
|
8
|
+
|
9
|
+
base_uri MicroRb::Configuration.instance.gateway_uri
|
10
|
+
|
11
|
+
def self.call(service:, method:, params:, klass_response: nil)
|
12
|
+
response = post(MicroRb::Configuration.instance.gateway_rpc,
|
13
|
+
options(service: service, method: method, request: params))
|
14
|
+
|
15
|
+
return klass_response.new(response.to_h.symbolize_keys!) if klass_response
|
16
|
+
|
17
|
+
response
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module MicroRb
|
5
|
+
module Clients
|
6
|
+
class Sidecar
|
7
|
+
include Base
|
8
|
+
|
9
|
+
base_uri MicroRb::Configuration.instance.sidecar_uri
|
10
|
+
|
11
|
+
def self.register(service)
|
12
|
+
post(registry_path, options(service))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.remove(service)
|
16
|
+
delete(registry_path, options(service))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.registry_path
|
20
|
+
MicroRb::Configuration.instance.sidecar_registry
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/micro/configuration.rb
CHANGED
@@ -5,9 +5,11 @@ module MicroRb
|
|
5
5
|
class Configuration
|
6
6
|
include Singleton
|
7
7
|
|
8
|
-
|
9
|
-
attr_accessor :sidecar_host
|
10
|
-
|
8
|
+
# Sidecar settings
|
9
|
+
attr_accessor :sidecar_registry, :sidecar_host, :sidecar_port
|
10
|
+
|
11
|
+
# API gateway settings
|
12
|
+
attr_accessor :gateway_host, :gateway_port, :gateway_rpc
|
11
13
|
|
12
14
|
def self.configure
|
13
15
|
yield(instance) if block_given?
|
@@ -21,14 +23,28 @@ module MicroRb
|
|
21
23
|
"#{sidecar_uri}#{sidecar_registry}"
|
22
24
|
end
|
23
25
|
|
26
|
+
def gateway_uri
|
27
|
+
"#{gateway_host}:#{gateway_port}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def gateway_rpc_uri
|
31
|
+
"#{gateway_uri}#{gateway_rpc}"
|
32
|
+
end
|
33
|
+
|
24
34
|
private
|
25
35
|
|
26
36
|
def initialize
|
27
37
|
yield(self) if block_given?
|
28
38
|
|
39
|
+
# Default sidecar settings
|
29
40
|
self.sidecar_host ||= 'http://127.0.0.1'
|
30
41
|
self.sidecar_registry ||= '/registry'
|
31
42
|
self.sidecar_port ||= '8081'
|
43
|
+
|
44
|
+
# Default API gateway settings
|
45
|
+
self.gateway_host ||= 'http://127.0.0.1'
|
46
|
+
self.gateway_rpc ||= '/rpc'
|
47
|
+
self.gateway_port ||= '3002'
|
32
48
|
end
|
33
49
|
end
|
34
50
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../../../lib/microrb'
|
5
|
+
require_relative '../examples/proto/fib_pb'
|
6
|
+
require 'rack/handler/puma'
|
7
|
+
|
8
|
+
# This example was to show the usage of puma as well as making RPC calls to services.
|
9
|
+
class FibHandler
|
10
|
+
include MicroRb::Handler
|
11
|
+
include MicroRb::FibPb
|
12
|
+
|
13
|
+
handler name: :fibonacci, metadata: { hello: 'Micro-Rb' }, rpc_method: :fibonacci
|
14
|
+
|
15
|
+
def fibonacci(request: Request.new, response: Response.new)
|
16
|
+
if (0..1).cover?(request.n)
|
17
|
+
response.n = request.n
|
18
|
+
|
19
|
+
return response
|
20
|
+
end
|
21
|
+
|
22
|
+
left = rpc_call(Request.new(n: request.n - 1))
|
23
|
+
right = rpc_call(Request.new(n: request.n - 2))
|
24
|
+
|
25
|
+
response.n = left + right
|
26
|
+
|
27
|
+
response
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def rpc_call(request)
|
33
|
+
MicroRb::Clients::Rpc.call(service: :test,
|
34
|
+
method: 'FibHandler.fibonacci',
|
35
|
+
params: request,
|
36
|
+
klass_response: Response).n
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
server = MicroRb::Servers::Web.new(:test, debug: true, metadata: { example: 'Fib Service' }, server: :puma)
|
41
|
+
server.add_handler FibHandler.new
|
42
|
+
server.start!
|
43
|
+
|
44
|
+
# MicroRb::Clients::Rpc.call(service: :test, method: 'FibHandler.fibonacci', params: { n: 15 } )
|
45
|
+
# {
|
46
|
+
# "n" => 610
|
47
|
+
# }
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: fib.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_message "micro_rb.fib_pb.Request" do
|
8
|
+
optional :n, :int32, 1
|
9
|
+
end
|
10
|
+
add_message "micro_rb.fib_pb.Response" do
|
11
|
+
optional :n, :int32, 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module MicroRb
|
16
|
+
module FibPb
|
17
|
+
Request = Google::Protobuf::DescriptorPool.generated_pool.lookup("micro_rb.fib_pb.Request").msgclass
|
18
|
+
Response = Google::Protobuf::DescriptorPool.generated_pool.lookup("micro_rb.fib_pb.Response").msgclass
|
19
|
+
end
|
20
|
+
end
|
@@ -20,7 +20,7 @@ module MicroRb
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def rpc_method(method)
|
23
|
-
rpc_methods[method.to_sym]
|
23
|
+
rpc_methods[method.to_sym].clone
|
24
24
|
end
|
25
25
|
|
26
26
|
def rpc_method?(method)
|
@@ -35,17 +35,17 @@ module MicroRb
|
|
35
35
|
rpc_method(method).owner::Request.new(*params)
|
36
36
|
end
|
37
37
|
|
38
|
+
def call_rpc_method(method, params)
|
39
|
+
rpc_method(method)
|
40
|
+
.call(request: rpc_method_request(method, params),
|
41
|
+
response: rpc_method_response(method))
|
42
|
+
end
|
43
|
+
|
38
44
|
private
|
39
45
|
|
40
46
|
def validate_handler(handler)
|
41
|
-
unless handler.is_a?(MicroRb::Handler)
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
if handlers.include?(handler.name)
|
46
|
-
raise "Handler #{handler.name} has already been registered."
|
47
|
-
end
|
48
|
-
|
47
|
+
raise "Handler must be of type MicroRb::Handler got #{handler.class}" unless handler.is_a?(MicroRb::Handler)
|
48
|
+
raise "Handler #{handler.name} has already been registered." if handlers.include?(handler.name)
|
49
49
|
raise "Handler #{handler.name} is invalid." unless handler.valid?
|
50
50
|
end
|
51
51
|
|
data/lib/micro/proto/debug.proto
CHANGED
data/lib/micro/servers/web.rb
CHANGED
@@ -9,8 +9,8 @@ require 'multi_json'
|
|
9
9
|
module MicroRb
|
10
10
|
module Servers
|
11
11
|
class Web
|
12
|
-
attr_accessor :host, :port, :show_errors, :debug, :metadata, :version
|
13
|
-
|
12
|
+
attr_accessor :host, :port, :show_errors, :debug, :metadata, :version,
|
13
|
+
:handler_manager, :name, :node_id, :server
|
14
14
|
|
15
15
|
REQUIRED_TYPES = { method: [String], params: [Hash, Array],
|
16
16
|
id: [String, Integer, NilClass] }.freeze
|
@@ -18,10 +18,10 @@ module MicroRb
|
|
18
18
|
REQUIRED_KEYS = ['method'].freeze
|
19
19
|
|
20
20
|
def initialize(name, opts = {})
|
21
|
-
self.port = opts.delete(:port)
|
22
|
-
self.host = opts.delete(:host)
|
21
|
+
self.port = opts.delete(:port) || 3000
|
22
|
+
self.host = opts.delete(:host) || '0.0.0.0'
|
23
23
|
self.metadata = opts.delete(:metadata) || {}
|
24
|
-
self.version = opts.delete(:version)
|
24
|
+
self.version = opts.delete(:version) || '0.0.1'
|
25
25
|
self.debug = opts.delete(:debug)
|
26
26
|
self.name = name
|
27
27
|
self.node_id = "#{name}-#{SecureRandom.uuid}"
|
@@ -40,7 +40,7 @@ module MicroRb
|
|
40
40
|
add_handler(MicroRb::Handlers::Debug.new)
|
41
41
|
|
42
42
|
# Value will raise an error on anything not 2XX
|
43
|
-
MicroRb::Sidecar
|
43
|
+
MicroRb::Clients::Sidecar.register(self).response.value
|
44
44
|
|
45
45
|
if debug
|
46
46
|
MicroRb.logger
|
@@ -79,27 +79,17 @@ module MicroRb
|
|
79
79
|
|
80
80
|
return resp.finish unless req.post?
|
81
81
|
|
82
|
-
resp.write
|
82
|
+
resp.write handle_request(req.body.read)
|
83
83
|
resp.finish
|
84
84
|
end
|
85
85
|
|
86
|
-
def process(content)
|
87
|
-
response = handle_request(content)
|
88
|
-
|
89
|
-
MultiJson.encode(response)
|
90
|
-
end
|
91
|
-
|
92
86
|
def create_response(request)
|
93
87
|
method = request['method'].strip.to_sym
|
94
88
|
params = request['params'].map(&:symbolize_keys!)
|
95
89
|
|
96
|
-
unless handler_manager.rpc_method?(method)
|
97
|
-
return error_response(Error::MethodNotFound.new(method), request)
|
98
|
-
end
|
90
|
+
return error_response(Error::MethodNotFound.new(method), request) unless handler_manager.rpc_method?(method)
|
99
91
|
|
100
|
-
|
101
|
-
response = rpc_method.call(request: handler_manager.rpc_method_request(method, params),
|
102
|
-
response: handler_manager.rpc_method_response(method))
|
92
|
+
response = handler_manager.call_rpc_method(method, params)
|
103
93
|
|
104
94
|
success_response(request, response)
|
105
95
|
end
|
@@ -119,7 +109,7 @@ module MicroRb
|
|
119
109
|
response = error_response(Error::InternalError.new(e), request)
|
120
110
|
end
|
121
111
|
|
122
|
-
response
|
112
|
+
MultiJson.encode(response)
|
123
113
|
end
|
124
114
|
|
125
115
|
private
|
@@ -150,7 +140,7 @@ module MicroRb
|
|
150
140
|
def add_finalizer_hook!
|
151
141
|
at_exit do
|
152
142
|
MicroRb.logger.debug("Shutting down #{name}:#{host}:#{port}") if debug
|
153
|
-
MicroRb::Sidecar
|
143
|
+
MicroRb::Clients::Sidecar.remove(self)
|
154
144
|
end
|
155
145
|
end
|
156
146
|
|
data/lib/micro/version.rb
CHANGED
data/lib/microrb.rb
CHANGED
@@ -15,9 +15,10 @@ end
|
|
15
15
|
|
16
16
|
require 'micro/version'
|
17
17
|
require 'micro/configuration'
|
18
|
-
require 'micro/
|
19
|
-
require 'micro/sidecar
|
20
|
-
require 'micro/
|
18
|
+
require 'micro/clients/base'
|
19
|
+
require 'micro/clients/sidecar'
|
20
|
+
require 'micro/clients/rpc'
|
21
|
+
require 'micro/clients/http'
|
21
22
|
require 'micro/handler'
|
22
23
|
require 'micro/handler_manager'
|
23
24
|
require 'micro/servers/web'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: micro-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Medeiros
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -217,7 +217,14 @@ files:
|
|
217
217
|
- bin/setup
|
218
218
|
- lib/micro-rb.rb
|
219
219
|
- lib/micro/cli.rb
|
220
|
+
- lib/micro/clients/base.rb
|
221
|
+
- lib/micro/clients/http.rb
|
222
|
+
- lib/micro/clients/rpc.rb
|
223
|
+
- lib/micro/clients/sidecar.rb
|
220
224
|
- lib/micro/configuration.rb
|
225
|
+
- lib/micro/examples/fib.rb
|
226
|
+
- lib/micro/examples/proto/fib.proto
|
227
|
+
- lib/micro/examples/proto/fib_pb.rb
|
221
228
|
- lib/micro/examples/proto/sum.proto
|
222
229
|
- lib/micro/examples/proto/sum_pb.rb
|
223
230
|
- lib/micro/examples/sum.rb
|
@@ -229,9 +236,6 @@ files:
|
|
229
236
|
- lib/micro/proto/debug_pb.rb
|
230
237
|
- lib/micro/servers/error.rb
|
231
238
|
- lib/micro/servers/web.rb
|
232
|
-
- lib/micro/sidecar/base.rb
|
233
|
-
- lib/micro/sidecar/call.rb
|
234
|
-
- lib/micro/sidecar/register.rb
|
235
239
|
- lib/micro/version.rb
|
236
240
|
- lib/microrb.rb
|
237
241
|
- micro-rb.gemspec
|
data/lib/micro/sidecar/call.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module MicroRb
|
5
|
-
module Sidecar
|
6
|
-
class Call
|
7
|
-
include MicroRb::Sidecar::Base
|
8
|
-
|
9
|
-
def self.rpc(path, request)
|
10
|
-
post(path, options(request))
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.http(path, request)
|
14
|
-
post(path, query: request)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module MicroRb
|
5
|
-
module Sidecar
|
6
|
-
class Register
|
7
|
-
include MicroRb::Sidecar::Base
|
8
|
-
|
9
|
-
def self.notify(service)
|
10
|
-
post(registry_uri, options(service))
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.remove(service)
|
14
|
-
delete(registry_uri, options(service))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|