flying-sphinx 1.3.1 → 2.0.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 +5 -5
- data/.travis.yml +4 -6
- data/Appraisals +14 -10
- data/HISTORY +8 -0
- data/README.textile +4 -6
- data/flying-sphinx.gemspec +1 -2
- data/lib/flying_sphinx.rb +5 -15
- data/lib/flying_sphinx/cli.rb +17 -80
- data/lib/flying_sphinx/commands.rb +35 -0
- data/lib/flying_sphinx/commands/base.rb +86 -0
- data/lib/flying_sphinx/commands/clear.rb +7 -0
- data/lib/flying_sphinx/commands/configure.rb +7 -0
- data/lib/flying_sphinx/commands/index_sql.rb +33 -0
- data/lib/flying_sphinx/commands/merge.rb +17 -0
- data/lib/flying_sphinx/commands/prepare.rb +7 -0
- data/lib/flying_sphinx/commands/rebuild.rb +7 -0
- data/lib/flying_sphinx/commands/reset.rb +7 -0
- data/lib/flying_sphinx/commands/restart.rb +7 -0
- data/lib/flying_sphinx/commands/rotate.rb +7 -0
- data/lib/flying_sphinx/commands/running.rb +7 -0
- data/lib/flying_sphinx/commands/start.rb +7 -0
- data/lib/flying_sphinx/commands/start_attached.rb +10 -0
- data/lib/flying_sphinx/commands/stop.rb +7 -0
- data/lib/flying_sphinx/configuration_options.rb +11 -5
- data/lib/flying_sphinx/configurer.rb +7 -2
- data/lib/flying_sphinx/railtie.rb +7 -5
- data/lib/flying_sphinx/rake_interface.rb +25 -0
- data/lib/flying_sphinx/response/invalid.rb +1 -1
- data/lib/flying_sphinx/setting_files.rb +2 -2
- data/lib/flying_sphinx/tasks.rb +31 -24
- data/lib/flying_sphinx/tasks/deprecated.rb +31 -0
- data/lib/flying_sphinx/tasks/replaced.rb +27 -0
- data/lib/flying_sphinx/version.rb +1 -1
- data/spec/acceptance/configuring_spec.rb +7 -7
- data/spec/acceptance/start_or_stop_sphinx_spec.rb +7 -4
- data/spec/flying_sphinx/action_spec.rb +1 -1
- data/spec/flying_sphinx/commands/clear_spec.rb +22 -0
- data/spec/flying_sphinx/commands/configure_spec.rb +38 -0
- data/spec/flying_sphinx/commands/index_sql_spec.rb +69 -0
- data/spec/flying_sphinx/commands/merge_spec.rb +30 -0
- data/spec/flying_sphinx/commands/rebuild_spec.rb +26 -0
- data/spec/flying_sphinx/commands/reset_spec.rb +26 -0
- data/spec/flying_sphinx/commands/restart_spec.rb +23 -0
- data/spec/flying_sphinx/commands/rotate_spec.rb +22 -0
- data/spec/flying_sphinx/commands/running_spec.rb +24 -0
- data/spec/flying_sphinx/commands/start_attached_spec.rb +14 -0
- data/spec/flying_sphinx/commands/start_spec.rb +23 -0
- data/spec/flying_sphinx/commands/stop_spec.rb +23 -0
- data/spec/flying_sphinx/configurer_spec.rb +147 -0
- data/spec/support/command_helpers.rb +11 -0
- data/spec/support/multipart.rb +10 -6
- metadata +51 -27
- data/lib/flying_sphinx/binary.rb +0 -7
- data/lib/flying_sphinx/binary/translator.rb +0 -48
- data/lib/flying_sphinx/controller.rb +0 -104
- data/lib/flying_sphinx/rails.rb +0 -7
- data/lib/flying_sphinx/sphinxql.rb +0 -7
- data/lib/flying_sphinx/sphinxql/translator.rb +0 -26
- data/spec/flying_sphinx/controller_spec.rb +0 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9e456647fed387b52501630a4ccfcbb68997dac89175eb6f4d774373f4022cfe
|
4
|
+
data.tar.gz: 06ebf9bd4a0c560f1df0892c58d36cab1b19d4571e47d37cd9ff16d32bfd3096
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6de104433df80fe158a321f122ab4d745b455e3132da6d4fac4a14d65d5dab481ce01b5992882c7216746856e93a7f6b5afc9422ab8f31d59fc89f329410bd64
|
7
|
+
data.tar.gz: b8a333189a913fbc7011c63fa12f8d9c1c39037f22c00dc61d6bf77836e86107dd8f31a38b3867040410f8b480851b16b07b55829514fa3b7b4f7a1cc5a3ae73
|
data/.travis.yml
CHANGED
data/Appraisals
CHANGED
@@ -1,25 +1,29 @@
|
|
1
1
|
appraise 'rails-3.2' do
|
2
2
|
gem 'rails', '~> 3.2.18'
|
3
3
|
gem 'faraday', '~> 0.8.0'
|
4
|
-
end if RUBY_VERSION.to_f
|
4
|
+
end if RUBY_VERSION.to_f <= 2.3
|
5
5
|
|
6
6
|
appraise 'rails-4.0' do
|
7
7
|
gem 'rails', '~> 4.0.5'
|
8
8
|
gem 'faraday', '~> 0.9.0'
|
9
|
-
end if RUBY_VERSION.to_f
|
9
|
+
end if RUBY_VERSION.to_f <= 2.3
|
10
10
|
|
11
11
|
appraise 'rails-4.1' do
|
12
|
-
gem 'rails',
|
13
|
-
end if RUBY_VERSION.to_f
|
12
|
+
gem 'rails', '~> 4.1.16'
|
13
|
+
end if RUBY_VERSION.to_f <= 2.3
|
14
14
|
|
15
15
|
appraise 'rails-4.2' do
|
16
|
-
gem 'rails',
|
17
|
-
end if RUBY_VERSION.to_f
|
16
|
+
gem 'rails', '~> 4.2.10'
|
17
|
+
end if RUBY_VERSION.to_f <= 2.3
|
18
18
|
|
19
19
|
appraise 'rails-5.0' do
|
20
|
-
gem 'rails',
|
21
|
-
end
|
20
|
+
gem 'rails', '~> 5.0.6'
|
21
|
+
end
|
22
22
|
|
23
23
|
appraise 'rails-5.1' do
|
24
|
-
gem 'rails',
|
25
|
-
end
|
24
|
+
gem 'rails', '~> 5.1.4'
|
25
|
+
end
|
26
|
+
|
27
|
+
appraise 'rails-5.2' do
|
28
|
+
gem 'rails', '~> 5.2.0'
|
29
|
+
end
|
data/HISTORY
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
2.0.0 - 10th April 2018
|
2
|
+
* Add support for Manticore (via engine setting in config/thinking_sphinx.yml).
|
3
|
+
* Drop support for Thinking Sphinx 3.x or older.
|
4
|
+
* Drop support for ActiveRecord/Rails 3.1 or older.
|
5
|
+
* Drop support for Ruby 2.1 or older.
|
6
|
+
* Deprecate fs tasks and the flying-sphinx CLI tool.
|
7
|
+
* Use Thinking Sphinx v4's new task/command architecture, and so all the ts rake tasks perform the appropriate behaviour on Flying Sphinx.
|
8
|
+
|
1
9
|
1.3.1 - 4th December 2017
|
2
10
|
* Fix call to generate real-time data for thinking-sphinx v3.4+.
|
3
11
|
|
data/README.textile
CHANGED
@@ -9,15 +9,13 @@ This is all covered pretty well on "the Flying Sphinx site":http://flying-sphinx
|
|
9
9
|
<pre><code>gem 'flying-sphinx',
|
10
10
|
:git => 'git://github.com/flying-sphinx/flying-sphinx.git',
|
11
11
|
:branch => 'master',
|
12
|
-
:ref => '
|
12
|
+
:ref => 'e72b86b56a'</code></pre>
|
13
13
|
|
14
14
|
h2. Compatibility and Limitations
|
15
15
|
|
16
|
-
|
16
|
+
The current (2.x) releases support Thinking Sphinx v4+, ActiveRecord/Rails 3.2+, and Ruby 2.2+.
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
There are limitations with Heroku's setup and Sphinx/Thinking Sphinx functionality - again, the official documentation "covers this":http://flying-sphinx.com/docs#limitations, so have a read there.
|
18
|
+
If you are using older versions of any of these, please use v1.3.1 (which supports Thinking Sphinx v1.5+, ActiveRecord/Rails 2.3.6+, and Ruby 1.9.3+).
|
21
19
|
|
22
20
|
If you're still using Ruby 1.8.7, flying-sphinx 1.2.1 is the last release to support that.
|
23
21
|
|
@@ -40,4 +38,4 @@ h2. Contributors
|
|
40
38
|
|
41
39
|
h2. Licence
|
42
40
|
|
43
|
-
Copyright © 2011-
|
41
|
+
Copyright © 2011-2018 Pat Allan, released under an MIT licence.
|
data/flying-sphinx.gemspec
CHANGED
@@ -22,8 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_runtime_dependency 'gzipped_tar', '~> 0.0.3'
|
23
23
|
s.add_runtime_dependency 'multi_json', '>= 1.3.0'
|
24
24
|
s.add_runtime_dependency 'pusher-client', '~> 0.3'
|
25
|
-
s.add_runtime_dependency '
|
26
|
-
s.add_runtime_dependency 'thinking-sphinx', '>= 1.5.0'
|
25
|
+
s.add_runtime_dependency 'thinking-sphinx', '>= 4.0.0'
|
27
26
|
|
28
27
|
s.add_development_dependency 'appraisal', '~> 2.2'
|
29
28
|
s.add_development_dependency 'dotenv', '~> 0.11.1'
|
data/lib/flying_sphinx.rb
CHANGED
@@ -20,22 +20,13 @@ module FlyingSphinx
|
|
20
20
|
def self.logger=(logger)
|
21
21
|
@logger = logger
|
22
22
|
end
|
23
|
-
|
24
|
-
def self.translator
|
25
|
-
@translator
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.translator=(translator)
|
29
|
-
@translator = translator
|
30
|
-
end
|
31
23
|
end
|
32
24
|
|
33
25
|
require 'multi_json'
|
34
26
|
require 'ey-hmac'
|
35
27
|
require 'faraday'
|
36
28
|
require 'gzipped_tar'
|
37
|
-
require '
|
38
|
-
require 'riddle/0.9.9'
|
29
|
+
require 'thinking_sphinx'
|
39
30
|
require 'pusher-client'
|
40
31
|
|
41
32
|
PusherClient.logger = FlyingSphinx.logger
|
@@ -43,14 +34,13 @@ PusherClient.logger = FlyingSphinx.logger
|
|
43
34
|
require 'flying_sphinx/version'
|
44
35
|
require 'flying_sphinx/action'
|
45
36
|
require 'flying_sphinx/api'
|
46
|
-
require 'flying_sphinx/binary'
|
47
37
|
require 'flying_sphinx/cli'
|
38
|
+
require 'flying_sphinx/commands'
|
48
39
|
require 'flying_sphinx/configuration'
|
49
40
|
require 'flying_sphinx/configuration_options'
|
50
41
|
require 'flying_sphinx/configurer'
|
51
|
-
require 'flying_sphinx/
|
42
|
+
require 'flying_sphinx/rake_interface'
|
52
43
|
require 'flying_sphinx/setting_files'
|
53
|
-
require 'flying_sphinx/sphinxql'
|
54
44
|
|
55
45
|
require 'flying_sphinx/request/hmac'
|
56
46
|
require 'flying_sphinx/response/invalid'
|
@@ -59,6 +49,6 @@ require 'flying_sphinx/response/logger'
|
|
59
49
|
|
60
50
|
if defined?(Rails) && defined?(Rails::Railtie)
|
61
51
|
require 'flying_sphinx/railtie'
|
62
|
-
elsif defined?(Rails) && defined?(Rails::Plugin)
|
63
|
-
require 'flying_sphinx/rails'
|
64
52
|
end
|
53
|
+
|
54
|
+
ThinkingSphinx.rake_interface = FlyingSphinx::RakeInterface
|
data/lib/flying_sphinx/cli.rb
CHANGED
@@ -1,94 +1,31 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
|
3
1
|
class FlyingSphinx::CLI
|
4
|
-
extend Forwardable
|
5
|
-
|
6
2
|
COMMANDS = {
|
7
|
-
'configure' =>
|
8
|
-
'index' =>
|
9
|
-
'setup' =>
|
10
|
-
'start' =>
|
11
|
-
'stop' =>
|
12
|
-
'restart' =>
|
13
|
-
'rebuild' =>
|
14
|
-
'regenerate' =>
|
3
|
+
'configure' => "ts:configure",
|
4
|
+
'index' => "ts:index",
|
5
|
+
'setup' => "ts:index",
|
6
|
+
'start' => "ts:start",
|
7
|
+
'stop' => "ts:stop",
|
8
|
+
'restart' => "ts:restart",
|
9
|
+
'rebuild' => "ts:rebuild",
|
10
|
+
'regenerate' => "ts:rebuild"
|
15
11
|
}
|
16
12
|
|
17
|
-
def_delegators :controller, :start, :stop, :restart
|
18
|
-
|
19
13
|
def initialize(command, arguments = [])
|
20
14
|
@command, @arguments = command, arguments
|
21
15
|
end
|
22
16
|
|
23
17
|
def run
|
24
|
-
|
25
|
-
raise "Unknown command #{@command}" if
|
26
|
-
|
27
|
-
methods.all? do |method|
|
28
|
-
FlyingSphinx.logger.info "Executing Action: #{method}"
|
29
|
-
result = send method
|
30
|
-
FlyingSphinx.logger.info "Action Finished: #{method}"
|
31
|
-
|
32
|
-
result
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def configuration
|
39
|
-
@configuration ||= FlyingSphinx::Configuration.new
|
40
|
-
end
|
41
|
-
|
42
|
-
def configure
|
43
|
-
if @arguments.empty?
|
44
|
-
load_rails
|
45
|
-
|
46
|
-
controller.configure
|
47
|
-
else
|
48
|
-
controller.configure File.read(@arguments.first)
|
49
|
-
end
|
50
|
-
|
51
|
-
true
|
52
|
-
end
|
18
|
+
task = COMMANDS[@command]
|
19
|
+
raise "Unknown command #{@command}" if task.nil?
|
53
20
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def index
|
59
|
-
indices = @arguments + [{:verbose => true}]
|
60
|
-
controller.index *indices
|
61
|
-
end
|
62
|
-
|
63
|
-
def load_rails
|
64
|
-
return unless ENV['RAILS_ENV']
|
65
|
-
|
66
|
-
boot = File.expand_path('config/boot', Dir.pwd)
|
67
|
-
return unless File.exist?("#{boot}.rb")
|
68
|
-
require boot
|
69
|
-
|
70
|
-
if defined?(Rails) && !defined?(Rails::Railtie)
|
71
|
-
require File.expand_path('config/environment', Dir.pwd)
|
72
|
-
require 'flying_sphinx/rails'
|
73
|
-
|
74
|
-
FlyingSphinx::Binary.load
|
75
|
-
else
|
76
|
-
require File.expand_path('config/application', Dir.pwd)
|
77
|
-
require 'flying_sphinx/railtie'
|
78
|
-
|
79
|
-
Rails.application.require_environment!
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def rebuild
|
84
|
-
load_rails
|
85
|
-
|
86
|
-
controller.rebuild
|
87
|
-
end
|
21
|
+
puts <<-MESSAGE
|
22
|
+
The flying_sphinx CLI tool is now deprecated. Please use the standard Thinking
|
23
|
+
Sphinx tasks instead. (Thinking Sphinx tasks will now invoke the appropriate
|
24
|
+
behaviour for both local and Flying Sphinx environments). In this case:
|
88
25
|
|
89
|
-
|
90
|
-
|
26
|
+
heroku run rake #{task}
|
27
|
+
MESSAGE
|
91
28
|
|
92
|
-
|
29
|
+
`bundle exec rake #{task}`
|
93
30
|
end
|
94
31
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module FlyingSphinx::Commands
|
2
|
+
end
|
3
|
+
|
4
|
+
require "flying_sphinx/commands/base"
|
5
|
+
require "flying_sphinx/commands/clear"
|
6
|
+
require "flying_sphinx/commands/configure"
|
7
|
+
require "flying_sphinx/commands/index_sql"
|
8
|
+
require "flying_sphinx/commands/merge"
|
9
|
+
require "flying_sphinx/commands/prepare"
|
10
|
+
require "flying_sphinx/commands/rebuild"
|
11
|
+
require "flying_sphinx/commands/reset"
|
12
|
+
require "flying_sphinx/commands/restart"
|
13
|
+
require "flying_sphinx/commands/rotate"
|
14
|
+
require "flying_sphinx/commands/running"
|
15
|
+
require "flying_sphinx/commands/start"
|
16
|
+
require "flying_sphinx/commands/start_attached"
|
17
|
+
require "flying_sphinx/commands/stop"
|
18
|
+
|
19
|
+
ThinkingSphinx::Commander.registry.merge!(
|
20
|
+
:clear => FlyingSphinx::Commands::Clear,
|
21
|
+
:clear_real_time => FlyingSphinx::Commands::Clear,
|
22
|
+
:clear_sql => FlyingSphinx::Commands::Clear,
|
23
|
+
:configure => FlyingSphinx::Commands::Configure,
|
24
|
+
:index_sql => FlyingSphinx::Commands::IndexSQL,
|
25
|
+
:merge => FlyingSphinx::Commands::Merge,
|
26
|
+
:prepare => FlyingSphinx::Commands::Prepare,
|
27
|
+
:rebuild => FlyingSphinx::Commands::Rebuild,
|
28
|
+
:reset => FlyingSphinx::Commands::Reset,
|
29
|
+
:restart => FlyingSphinx::Commands::Restart,
|
30
|
+
:rotate => FlyingSphinx::Commands::Rotate,
|
31
|
+
:running => FlyingSphinx::Commands::Running,
|
32
|
+
:start_attached => FlyingSphinx::Commands::StartAttached,
|
33
|
+
:start_detached => FlyingSphinx::Commands::Start,
|
34
|
+
:stop => FlyingSphinx::Commands::Stop
|
35
|
+
)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FlyingSphinx::Commands::Base < ThinkingSphinx::Commands::Base
|
4
|
+
DEFAULT_TIMEOUT = 60
|
5
|
+
INDEX_TIMEOUT = 60 * 60 * 3 # 3 hours
|
6
|
+
ERROR_MESSAGES = {
|
7
|
+
"BLOCKED" => <<-TXT,
|
8
|
+
BLOCKED: Single-index processing is not permitted for your plan level
|
9
|
+
TXT
|
10
|
+
"UNCONFIGURED" => <<-TXT,
|
11
|
+
UNCONFIGURED: This command can only be run once you have provided your Sphinx
|
12
|
+
configuration (via the ts:configure or ts:rebuild tasks).
|
13
|
+
TXT
|
14
|
+
"INVALID PATH" => <<-TXT
|
15
|
+
INVALID PATH: Something has gone wrong with the uploading of your configuration.
|
16
|
+
Please contact Flying Sphinx Support: http://support.flying-sphinx.com
|
17
|
+
TXT
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
def call_with_handling
|
21
|
+
call
|
22
|
+
rescue FlyingSphinx::Error => error
|
23
|
+
handle_failure error
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def api
|
29
|
+
@api ||= options[:api] || FlyingSphinx::Configuration.new.api
|
30
|
+
end
|
31
|
+
|
32
|
+
def flying_sphinx_settings
|
33
|
+
configuration.settings.fetch("flying_sphinx", {})
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_failure(error)
|
37
|
+
stream.puts <<-TXT
|
38
|
+
|
39
|
+
The Flying Sphinx command failed:
|
40
|
+
Class: #{self.class.name}
|
41
|
+
Error: #{error.message}
|
42
|
+
|
43
|
+
If everything looks to be in order, please try the command again. If the error
|
44
|
+
persists, please contact Flying Sphinx Support: http://support.flying-sphinx.com
|
45
|
+
|
46
|
+
TXT
|
47
|
+
|
48
|
+
raise error
|
49
|
+
end
|
50
|
+
|
51
|
+
def index_timeout
|
52
|
+
flying_sphinx_settings["index_timeout"] || INDEX_TIMEOUT
|
53
|
+
end
|
54
|
+
|
55
|
+
def run_action(action, timeout = default_timeout, parameters = {})
|
56
|
+
FlyingSphinx.logger.info "Executing Action: #{action}"
|
57
|
+
FlyingSphinx::Action.perform api.identifier, timeout do
|
58
|
+
send_action action, parameters
|
59
|
+
end
|
60
|
+
FlyingSphinx.logger.info "Action Finished: #{action}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_action_with_path(action, timeout = default_timeout)
|
64
|
+
path = FlyingSphinx::Configurer.call api
|
65
|
+
|
66
|
+
run_action action, timeout, :path => path
|
67
|
+
end
|
68
|
+
|
69
|
+
def send_action(action, parameters = {})
|
70
|
+
response = api.post '/perform', parameters.merge(:action => action)
|
71
|
+
|
72
|
+
if ERROR_MESSAGES.keys.include?(response["status"])
|
73
|
+
raise FlyingSphinx::Error, ERROR_MESSAGES[response["status"]]
|
74
|
+
end
|
75
|
+
|
76
|
+
if response["status"] != "OK"
|
77
|
+
raise FlyingSphinx::Error, "Unknown Exception: #{response["status"]}"
|
78
|
+
end
|
79
|
+
|
80
|
+
response
|
81
|
+
end
|
82
|
+
|
83
|
+
def default_timeout
|
84
|
+
flying_sphinx_settings["timeout"] || DEFAULT_TIMEOUT
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FlyingSphinx::Commands::IndexSQL < FlyingSphinx::Commands::Base
|
4
|
+
def call
|
5
|
+
if async?
|
6
|
+
send_action 'index', indexing_options.merge(:unique => 'true')
|
7
|
+
else
|
8
|
+
clear_jobs
|
9
|
+
|
10
|
+
run_action 'index', index_timeout, indexing_options
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def async?
|
17
|
+
indices.any? && !options[:verbose]
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear_jobs
|
21
|
+
::Delayed::Job.delete_all(
|
22
|
+
"handler LIKE '--- !ruby/object:FlyingSphinx::%'"
|
23
|
+
) if defined?(::Delayed) && ::Delayed::Job.table_exists?
|
24
|
+
end
|
25
|
+
|
26
|
+
def indexing_options
|
27
|
+
{:indices => indices.join(",")}
|
28
|
+
end
|
29
|
+
|
30
|
+
def indices
|
31
|
+
options[:indices] || []
|
32
|
+
end
|
33
|
+
end
|