Git Product home page Git Product logo

riddle's Introduction

Riddle

Build Status

Riddle is a Ruby library interfacing with the Sphinx full-text search tool. It is written by Pat Allan, and has been influenced by both Dmytro Shteflyuk's Ruby client and the original PHP client. It can be used for interactions with Sphinx's command-line tools searchd and indexer, sending search queries via the binary protocol, and programmatically generating Sphinx configuration files.

The syntax here, while closer to a usual Ruby approach than the PHP client, is quite old (Riddle was first published in 2007). While it would be nice to re-work things, it's really not a priority, given the bulk of Riddle's code is for Sphinx's deprecated binary protocol.

Installation

Riddle is available as a gem, so you can install it directly:

gem install riddle

Or include it in a Gemfile:

gem 'riddle', '~> 2.4'

Usage

As of version 1.0.0, Riddle supports multiple versions of Sphinx in the one gem - you'll need to require your specific version after a normal require, though. The latest distinct version is 2.1.0:

require 'riddle'
require 'riddle/2.1.0'

The full list of versions available are 0.9.8 (the initial base), 0.9.9, 1.10, 2.0.1, and 2.1.0. If you're using something more modern than 2.1.0, then just require that, and the rest should be fine (changes to the binary protocol since then are minimal).

Configuration

Riddle's structure for generating Sphinx configuration is very direct mapping to Sphinx's configuration options. First, create an instance of Riddle::Configuration:

config = Riddle::Configuration.new

This configuration instance has methods indexer, searchd and common, which return separate inner-configuration objects with methods mapping to the equivalent Sphinx settings. So, you may want to do the following:

config.indexer.mem_limit = '128M'
config.searchd.log       = '/my/log/file.log'

Similarly, there are two further methods indices and sources, which are arrays meant to hold instances of index and source inner-configuration objects respectively (all of which have methods matching their Sphinx settings). The available index classes are:

  • Riddle::Configuration::DistributedIndex
  • Riddle::Configuration::Index
  • Riddle::Configuration::RealtimeIndex
  • Riddle::Configuration::RemoteIndex
  • Riddle::Configuration::TemplateIndex

All of these index classes should be initialised with their name, and in the case of plain indices, their source objects. Remote indices take an address, port and name as their initialiser parameters.

index = Riddle::Configuration::Index.new 'articles', article_source_a, article_source_b
index.path    = '/path/to/index/files"
index.docinfo = 'external'

The available source classes are:

  • Riddle::Configuration::SQLSource
  • Riddle::Configuration::TSVSource
  • Riddle::Configuration::XMLSource

The initialising parameters are the name of the source, and the type of source:

source = Riddle::Configuration::SQLSource.new 'article_source', 'mysql'
source.sql_query = "SELECT id, title, body FROM articles"
source.sql_host  = "127.0.0.1"

Once you have created your configuration object tree, you can then generate the string representation and perhaps save it to a file:

File.write "sphinx.conf", configuration.render

It's also possible to parse an existing Sphinx configuration file into a configuration option tree:

configuration = Riddle::Configuration.parse! File.read('sphinx.conf')

Indexing and Starting/Stopping the Daemon

using Sphinx's command-line tools indexer and searchd via Riddle is all done via an instance of Riddle::Controller:

configuration_file = "/path/to/sphinx.conf"
configuration      = Riddle::Configuration.parse! File.read(configuration_file)
controller         = Riddle::Controller.new configuration, configuration_file

# set the path where the indexer and searchd binaries are located:
controller.bin_path = '/usr/local/bin'

# set different binary names if you're running a custom Sphinx installation:
controller.searchd_binary_name = 'sphinxsearchd'
controller.indexer_binary_name = 'sphinxindexer'

# process all indices:
controller.index
# process specific indices:
controller.index 'articles', 'books'
# rotate old index files out for the new ones:
controller.rotate

# start the daemon:
controller.start
# start the daemon and do not detach the process:
controller.start :nodetach => true
# stop the daemon:
controller.stop

The index, start and stop methods all accept a hash of options, and the :verbose option is respected in each case.

Each of these methods will return an instance of Riddle::CommandResult - or, if the command fails (as judged by the process status code), a Riddle::CommandFailedError exception is raised. These exceptions respond to the command_result method with the corresponding details.

SphinxQL Queries

Riddle does not have any code to send SphinxQL queries and commands to Sphinx. Because Sphinx uses the mysql41 protocol (thus, mimicing a MySQL database server), I recommend using the mysql2 gem instead. The connection code in Thinking Sphinx may provide some inspiration on this.

Binary Protocol Searching

Sphinx's legacy binary protocol does not have many of the more recent Sphinx features - such as real-time indices - as these are only available in the SphinxQL/mysql41 protocol. However, Riddle can still be used for the binary protocol if you wish.

To get started, just instantiate a Client object:

client = Riddle::Client.new # defaults to localhost and port 9312
client = Riddle::Client.new "sphinxserver.domain.tld", 3333 # custom settings

And then set the parameters to what you want, before running a query:

client.match_mode = :extended
client.query "Pat Allan @state Victoria"

The results from a query are similar to the other clients - but here's the details. It's a hash with the following keys:

  • :matches
  • :fields
  • :attributes
  • :attribute_names
  • :words
  • :total
  • :total_found
  • :time
  • :status
  • :warning (if appropriate)
  • :error (if appropriate)

The key :matches returns an array of hashes - the actual search results. Each hash has the document id (:doc), the result weighting (:weight), and a hash of the attributes for the document (:attributes).

The :fields and :attribute_names keys return list of fields and attributes for the documents. The key :attributes will return a hash of attribute name and type pairs, and :words returns a hash of hashes representing the words from the search, with the number of documents and hits for each, along the lines of:

results[:words]["Pat"] #=> {:docs => 12, :hits => 15}

:total, :total_found and :time return the number of matches available, the total number of matches (which may be greater than the maximum available), and the time in milliseconds that the query took to run.

:status is the error code for the query - and if there was a related warning, it will be under the :warning key. Fatal errors will be described under :error.

Contributing

Please note that this project has a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Riddle uses the git-flow process for development. The main branch is the latest released code (in a gem). The develop branch is what's coming in the next release. (There may be occasional feature and hotfix branches, although these are generally not pushed to GitHub.)

When submitting a patch to Riddle, please submit your pull request against the develop branch.

Contributors

Thanks to the following people who have contributed to Riddle in some shape or form:

  • Andrew Aksyonoff
  • Brad Greenlee
  • Lachie Cox
  • Jeremy Seitz
  • Mark Lane
  • Xavier Noria
  • Henrik Nye
  • Kristopher Chambers
  • Rob Anderton
  • Dylan Egan
  • Jerry Vos
  • Piotr Sarnacki
  • Tim Preston
  • Amir Yalon
  • Sam Goldstein
  • Matt Todd
  • Paco Guzmán
  • Greg Weber
  • Enrico Thierbach
  • Jason Lambert
  • Saberma
  • James Cook
  • Alexey Artamonov
  • Paul Gibler
  • Ngan Pham
  • Aaron Gilbralter
  • Steven Bristol
  • Ilia Lobsanov
  • Aleksey Morozov
  • S. Christoffer Eliesen
  • Rob Golkosky
  • Darcy Brown

riddle's People

Contributors

agibralter avatar alexeymorozov avatar darcy avatar dejan avatar dmeremyanin avatar drogus avatar epidemian avatar gregwebs avatar jdelstrother avatar jogaco avatar kslazarev avatar ktdreyer avatar lachie avatar madmax avatar mendable avatar mipearson avatar mtodd avatar ngan avatar nurey avatar olleolleolle avatar pat avatar radiospiel avatar richievos avatar robg avatar saberma avatar samg avatar stevenbristol avatar trevorsmith avatar useruby avatar yob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

riddle's Issues

Zero results (occasionally)

We moved from acts_as_sphinx last month to ThinkingSphinx and since then have been trying to track down an intermittent problem that we can't seem to get to the bottom of.

Basically, every so often... we'll get zero results back from sphinx queries that we know have a lot of results. However, when we look at the searchd.query.log on the sphinx server we see it showing that it's supposed to be returning a number of results.

Here.. a quick breakdown...

[Thu Mar 17 16:06:29.037 2011] 0.001 sec [all/3/ext 212 (3000,1000)] [tour_variation_core] tour
[Thu Mar 17 16:06:29.550 2011] 0.001 sec [all/3/ext 212 (3000,1000)] [tour_variation_core] tour
[Thu Mar 17 16:06:52.796 2011] 0.001 sec [all/3/ext 212 (3000,1000)] [tour_variation_core] tour
[Thu Mar 17 16:06:53.321 2011] 0.001 sec [all/3/ext 212 (3000,1000)] [tour_variation_core] tour

However, during this period... our app had one instance return zero results. (yet we're seeing 212 each time on the sphinx server).

Upon researching the problem, I found this thread which sounds like the closest behavior to what we're seeing.

Given that Riddle is our new client, I'm wondering if anybody else is seeing similar problems (on a fairly high-traffic site). I haven't dug too deep into the internals... but something is definitely happening after sphinx returns results and by the time our thinking-sphinx search gets it's collection back.

Any thoughts and/or suggestions on how to better diagnosis the problem on our end? Right now, inspecting the results from thinking-sphinx is just returning an empty array... so not too valuable at this point.

Also, we can't really reproduce this locally... only seems to be happening in production, which is on:

ruby 1.8.6 (2008-08-11 patchlevel 287) [x86_64-linux]

Thanks in advance for any assistance you can provide us!

Cheers,
Robby

drop mysql2 version dependency

Currently riddle requires mysql2 =0.3.2. I have been using it fine with 0.2.6, and mysql2 0.3.x is Rails 3 only now. The mysql2 author says to stick to mysql2 0.2.x for Rails 2 compatibility, and Riddle 1.3.3 certainly works with rails 2.3.11.

Address family not supported by protocol - socket(2)

Using rails-3.0.5, thinking-sphinx-2.0.3 and riddle-1.3.1.

When attempting to perform #save! on one of the models, getting this subj exception:

[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:567:in `initialize'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:567:in `new'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:567:in `initialise_socket'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:542:in `initialise_connection'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:493:in `open_socket'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:530:in `connect'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:597:in `request'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:226:in `run'
[GEM_ROOT]/gems/riddle-1.3.1/lib/riddle/client.rb:333:in `query'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:397:in `block (2 levels) in populate'
[GEM_ROOT]/gems/activesupport-3.0.5/lib/active_support/notifications.rb:52:in `block in instrument'
[GEM_ROOT]/gems/activesupport-3.0.5/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
[GEM_ROOT]/gems/activesupport-3.0.5/lib/active_support/notifications.rb:52:in `instrument'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:495:in `log'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:504:in `log'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:396:in `block in populate'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:545:in `call'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:545:in `retry_on_stale_index'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:394:in `populate'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search.rb:176:in `method_missing'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/search_methods.rb:395:in `search_for_id'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/active_record.rb:330:in `in_index?'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/active_record/attribute_updates.rb:46:in `update_index'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/active_record/attribute_updates.rb:23:in `block in update_attribute_values'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/active_record/attribute_updates.rb:16:in `each'
[GEM_ROOT]/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx/active_record/attribute_updates.rb:16:in `update_attribute_values'
[GEM_ROOT]/gems/activesupport-3.0.5/lib/active_support/callbacks.rb:459:in `_run_save_callbacks'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:277:in `create_or_update'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/persistence.rb:39:in `save'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/validations.rb:43:in `save'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/attribute_methods/dirty.rb:21:in `save'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:240:in `block (2 levels) in save'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:292:in `block in with_transaction_returning_status'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in `transaction'
[GEM_ROOT]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:207:in `transaction'
...

Strangely enough, all other models seems to work fine. I don't even have an idea what makes this particular model any different.

Test files included in the gem file

Currently theres 11 meg of SQL test files being included within the built Gem - the rest of the gem is tiny in comparison.

The gem test command went away quite some time ago, as did the test_files command still used the Gemspec

Do these still need to be included in the packaged Gem or can they be excluded - would you take a PR to exclude them?

Gem is Big

Because of the fixture data, the gem size is 4.7M. Especially when bundling gems, this makes me sad. Is it possible to not include this data in the gem?

String values in Client::Filter are not supported

Please add support for strings in Filter.

f = Riddle::Client::Filter.new('string_attr', ['my_value'])
f.query_message
 => "\000\000\000\vstring_attr\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"

sort-by attribute not found after updating to 1.5.10

After updating to Riddle 1.5.10 (from 1.5.9) my app began getting errors for each index which specifies has(updated_at, :sortable => true).

I tried rebuilding the config and index with several different gem configurations. I found that using thinking-sphinx-3.0.6 + riddle-1.5.9 still works with my config.

Errors like the one below were occurring for:
thinking-sphinx-3.0.6 + riddle-1.5.10
thinking-sphinx-3.1.0 + riddle-1.5.10

Here's an example with the relevant backtrace:

ThinkingSphinx::SphinxError - sort-by attribute 'updated_at' not found:
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/errors.rb:15:in `new_from_mysql'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/connection.rb:40:in `rescue in block in take'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/connection.rb:37:in `block in take'
  (gem) innertube-1.1.0/lib/innertube.rb:138:in `take'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/connection.rb:36:in `take'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/search/batch_inquirer.rb:16:in `results'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/middlewares/inquirer.rb:9:in `block in call'
  (gem) activesupport-3.2.16/lib/active_support/notifications.rb:123:in `block in instrument'
  (gem) activesupport-3.2.16/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  (gem) activesupport-3.2.16/lib/active_support/notifications.rb:123:in `instrument'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/search/context.rb:22:in `log'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/middlewares/inquirer.rb:8:in `call'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/middlewares/geographer.rb:11:in `call'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/middlewares/sphinxql.rb:14:in `call'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/middlewares/stale_id_filter.rb:10:in `call'
  (gem) middleware-0.1.0/lib/middleware/runner.rb:31:in `call'
  (gem) middleware-0.1.0/lib/middleware/builder.rb:102:in `call'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/search.rb:67:in `populate'
  /Users//.rvm/gems/ruby-1.9.3-p392@/bundler/gems/thinking-sphinx-3f2e3467d5ed/lib/thinking_sphinx/search.rb:113:in `method_missing'

Here is the index definition which corresponds with the error above:

ThinkingSphinx::Index.define :advisor, :with => :active_record, :delta => ThinkingSphinx::Deltas::SidekiqDelta do
  indexes(code_name)
  indexes(person.nickname)
  indexes(name)
  indexes(person.ssn)
  indexes(emails.address)
  indexes(phones.number)
  indexes(contracts.number)
  has(organization_id)
  has(updated_at, :sortable => true)
  set_property(:field_weights => {:name => 5})
end

Other info:

  • Database is Postegresql
  • Ruby 1.9.3-p392
  • mysql2 0.3.13 (also tried 0.3.14)
  • pg 0.17.0

Thanks! Let me know if I can provide any more useful information.

Riddle::Controller#stop doesn't give back any useful information, doesn't always work

Process.kill returns as soon as the system call goes through but sometimes the process hangs around and can cause running? to see that it's still running and can cause problems for tasks that need to restart Sphinx.

It would be useful to return the result of running? after calling Process.kill. This way we could retry or wait until it truly is no longer running. Or, possibly returning !running? to indicate that it was stopped or wasn't.

Alternatively, we could handle polling running? until it actually is stopped and then return.

Ability to change default connection method

There should be ability to change default connection method (TCPSocket.new).

For example for proc with standard behaviour:
Riddle::Client.connection_proc = Proc.new { |client| TCPSocket.new(client.server, client.port) }
or
riddle_instance.connection_proc = Proc.new { |client| TCPSocket.new(client.server, client.port) }

It will allow to hook custom connection methods, for example for DaemonController usage.

I've added support for such behavior in my fork http://github.com/drogus/riddle/ both for master and sphinx-0.9.9 branches.

Combing OR and AND filters

Hi Pat,

I'm trying to do the following: I've got content with tags, which are stored as multis in in sphinx.

Currently I'm finding content within a specific tag cloud by doing the following query:

  tag_cloud_tag_ids.each do |tag_id|
    riddle_client.filters << Riddle::Client::Filter.new('tag_ids', [tag_id] )
  end

  riddle.query('test')

So the content I want to find has to have ALL the tags in the tagcloud.

But now I want to search for content which is in either in tag cloud A or tag cloud B pseudo sql code example:

SELECT id FROM contents WHERE MATCH('test') AND (tag_ids IN(1) AND tag_ids IN(2)) OR (tag_ids IN(10) AND tag_ids IN(11));

Where tag_cloud A contains tags 1 & 2 and tag_cloud B 10 & 11.
Is there a way to do this in a single query with Sphinx? And with Riddle?

searchd and indexer sections as optional

Hi,
I use thinking_sphinx gem in my projects and I'd like to create only one sphinx config file for any of my applications that use sphinx on production server. Only one searchd process. I have an idea to do searchd and indexerconfiguration's sections as optional. Everything will still work on development and test ENVs as before. Currently riddle generates sphinx config file for each applications separately with indexer and searchd sections as you know.
What do you think? If you agree i will send pull request.

Escaping issues

Some of our indexed content occasionally contains gibberish that is not escaped properly by riddle. Consider the following example:

query = Riddle::Query.snippets("\\'", 'foo_core', 'foo')
=> "CALL SNIPPETS('\\\\'', 'foo_core', 'foo')"

ThinkingSphinx::Connection.new.query query
=> Mysql2::Error: sphinxql: syntax error, unexpected QUOTED_STRING, expecting ')' near '', 'foo_core', 'foo')'

I was wondering whether it is a good idea to use mysql2's escaping capabilities instead (Mysql2::Client#escape), or have you chosen not to do that for a particular reason? A working example:

ThinkingSphinx::Connection.new.client.escape("\\'")
=> "\\\\\\'"

query = "CALL SNIPPETS('\\\\\\'', 'foo_core', 'foo')"
ThinkingSphinx::Connection.new.query query
Mysql2::Error: unknown local index 'foo_core' in search request # Query ok!

Using Riddle to generate config files

I'm writing diploma thesis on full-text searching, and my goal is to compare all open-source full-text search engines. For that reason, I would like to communicate with Sphinx on a lower level (without ActiveRecord, just Riddle & Mysql2), to have more control.

What I would like to do is to be able to programatically configure Sphinx. I would like to configure which MySQL database to use, what kind of index (e.g. RT index) and so on. Now, I noticed that Riddle had all of these Configuration files, which looked like could help me, but they don't seem to be used inside of Riddle. If I understood correctly these are just declarations, and probably used only in Thinking Sphinx.

Do you have a suggestion for me how to use Riddle to achieve my goal? Are there some parts of Thinking Sphinx that I could reuse?

Index defining documentation

Hi!
Is there any documentation on index definition building using Riddle?
I see quite large library, but there are no even comments :)

Project is marked as PHP

In the github search for "riddle", this project is marked as PHP.
Switching that to Ruby would make it an easier find :)

problem with autotest

I am using Autotest and RCov for my tests. While the tests run fine (I leave my searchd running which might not be optimal) and rcov reports correctly, autotest fails to start:
/Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- riddle (MissingSourceFile)

Of course, irb and rails load the riddle gem just fine.
I have also tried to disable all autotest plugins I use with no luck.

Passenger + TS 2.0.3 fail

Simple app here to reproduce https://github.com/wulffeld/tsphinx203fail.

I think it has to do with the PATH not including /opt/local/bin where my indexer is located. Setting bin_path in sphinx.yml doesn't work.

Doesn't get passed the passenger error page:

Application root:
/Users/m/tsphinx203fail

Backtrace:

#   File    Line    Location
0   /Users/m/.bundler/gems/riddle-1.3.0/lib/riddle/auto_version.rb  15  in `exit'
1   /Users/m/.bundler/gems/riddle-1.3.0/lib/riddle/auto_version.rb  15  in `configure'
2   /Users/m/.bundler/gems/riddle-1.3.0/lib/riddle.rb   53 
3   /Users/m/.bundler/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx.rb 4   in `require'
4   /Users/m/.bundler/gems/thinking-sphinx-2.0.3/lib/thinking_sphinx.rb 4   
5   /Users/m/.bundler/gems/thinking-sphinx-2.0.3/lib/thinking-sphinx.rb 1   in `require'
6   /Users/m/.bundler/gems/thinking-sphinx-2.0.3/lib/thinking-sphinx.rb 1   
7   /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler/runtime.rb 68  in `require'
8   /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler/runtime.rb 68  in `require'
9   /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler/runtime.rb 66  in `each'
10  /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler/runtime.rb 66  in `require'
11  /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler/runtime.rb 55  in `each'
12  /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler/runtime.rb 55  in `require'
13  /opt/local/lib/ruby/gems/1.8/gems/bundler-1.0.10/lib/bundler.rb 120 in `require'
14  /Users/m/tsphinx203fail/config/application.rb   7   
15  /Users/m/tsphinx203fail/config/environment.rb   2   in `require'
16  /Users/m/tsphinx203fail/config/environment.rb   2   
17  config.ru   3   in `require'
18  config.ru   3   
19  /Users/m/.bundler/gems/rack-1.2.2/lib/rack/builder.rb   46  in `instance_eval'
20  /Users/m/.bundler/gems/rack-1.2.2/lib/rack/builder.rb   46  in `initialize'
21  config.ru   1   in `new'
22  config.ru   1   

using group_concat in select causes exception

Starting with 2.1.1-beta we can use group_concat in select together with group by, however when using it API returns attribute type 10, which is not handled and it raises exception.
When I tried to add handling to 10 => :next, it returned empty string, same as other string attributes.

Possible to generate incorrect queries even when using .escape

[43] pry(main)> Advert.search(Riddle::Query.escape('\\"')).first
ThinkingSphinx::SyntaxError: index advert_core,advert_delta: syntax error, unexpected $end near ''
from /usr/local/var/rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/thinking-sphinx-3.0.4/lib/thinking_sphinx/connection.rb:89:in `rescue in query_all'

:(

Context: I've started passing everything that comes in from params and goes to TS directly as a query through .escape, but we're still getting exceptions.

IMO .escape should return a string that can be passed as a query, regardless of input.

Allow group_by multiple fields

According to Sphinx, it is possible to do a group_by on multiple fields since version 2.1.2: http://sphinxsearch.com/bugs/view.php?id=1453.
However, when issuing a ThinkingSphinx search grouping by two fields (user_id, type), the query is not well constructed:

MyClass.search :with => {:some_id => 85}, :group_by => "user_id, type"
ThinkingSphinx::SyntaxError: sphinxql: syntax error, unexpected $undefined, expecting IDENT (or 5 other tokens) near '`user_id,` type LIMIT 0, 20; SHOW META'

Wierd problem, please help.

Hello,

I'm using Ruby 1.9.2 p320 with RVM, latest Sphinx (2.0.6), latests Thinking Sphinx (2.0.14), Rails 3.0.18 and Riddle 1.5.4, and I'm getting this wierd error only only in the browser, in the console it works like a charm:

undefined method unpack' for nil:NilClass riddle (1.5.4) lib/riddle/client/response.rb:25:innext_int'

More backtrace

riddle (1.5.4) lib/riddle/client/response.rb:25:in next_int' riddle (1.5.4) lib/riddle/client/response.rb:62:inblock in next_int_array'
riddle (1.5.4) lib/riddle/client/response.rb:61:in times' riddle (1.5.4) lib/riddle/client/response.rb:61:innext_int_array'
riddle (1.5.4) lib/riddle/client.rb:836:in attribute_from_type' riddle (1.5.4) lib/riddle/client.rb:270:inblock (3 levels) in run'
riddle (1.5.4) lib/riddle/client.rb:269:in each' riddle (1.5.4) lib/riddle/client.rb:269:inblock (2 levels) in run'
riddle (1.5.4) lib/riddle/client.rb:263:in each' riddle (1.5.4) lib/riddle/client.rb:263:inmap'
riddle (1.5.4) lib/riddle/client.rb:263:in block in run' riddle (1.5.4) lib/riddle/client.rb:228:incollect'
riddle (1.5.4) lib/riddle/client.rb:228:in run' riddle (1.5.4) lib/riddle/client.rb:338:inquery'
thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:429:in block (2 levels) in populate' activesupport (3.0.18) lib/active_support/notifications.rb:52:inblock in instrument'
activesupport (3.0.18) lib/active_support/notifications/instrumenter.rb:21:in instrument' activesupport (3.0.18) lib/active_support/notifications.rb:52:ininstrument'
thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:556:in log' thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:565:inlog'
thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:428:in block in populate' thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:606:incall'
thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:606:in retry_on_stale_index' thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:426:inpopulate'
thinking-sphinx (2.0.14) lib/thinking_sphinx/search.rb:95:in initialize' thinking-sphinx (2.0.14) lib/thinking_sphinx/search_methods.rb:368:innew'
thinking-sphinx (2.0.14) lib/thinking_sphinx/search_methods.rb:368:in `search'

Please if you can help me will be awesome.

Riddle::ResponseError (searchd error (status: 1): bad multi-query count 0...

Hi, we were using Thebes with Sphinx 2.0.1, and riddle was working fine, both with 3.0.7 and thebes stable and using git.

The problem arose after installing unicorn, which upgraded rack from 1.2.2 to 1.3.0, and still persists after downgrading to rack 1.2.2.

Using a plain Riddle::Client.query('hello', 'index') returns the same error.

Current Gemfile:

gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'mysql2' #, '< 0.3'
gem 'thinking-sphinx',
   :git     => 'git://github.com/freelancing-god/thinking-sphinx.git',
   :branch  => 'rails3'
#gem 'mysql2'#, '0.2.7' #, :git => 'git://github.com/rack/mysql2.git'

#gem "rack", '1.2.2' #, '>= 1.3.0.beta'
#gem 'thinking-sphinx', '2.0.3'
#gem 'riddle', :git=> 'git://github.com/freelancing-god/riddle.git'
#gem 'thebes' #, :git=> 'git://github.com/harvesthq/thebes.git'

We spent today downgrading and reinstalling gems but no combination removed the error.

persistent connections

Does riddle support sphinx's persistent connections? This post seems to indicate that it does..

http://www.mail-archive.com/[email protected]/msg02296.html

But there are no docs about it. Furthermore, it seems right now it couldn't work, since calling Client#query will end up calling Client#connect that always closes any socket after the request is done. So even activating persistent connections won't help much, since they will only persist for just one query.

If not implemented, that would be a good future feature.

Riddle::Query.escape misses some characters caught by Sphinx's EscapeString

It looks like this has been the case for a long time, so maybe it's intentional, but it appears that Riddle's escaping method misses some characters that have special meaning within the context of a Sphinx query.

The PHP API client that ships with Sphinx implements EscapeString as follows:

function EscapeString ( $string )
{
  $from = array ( '\\', '(',')','|','-','!','@','~','"','&', '/', '^', '$', '=', '<' );
  $to   = array ( '\\\\', '\(','\)','\|','\-','\!','\@','\~','\"', '\&', '\/', '\^', '\$', '\=', '\<' );
  return str_replace ( $from, $to, $string );
}

Riddle::Query.escape looks like this:

def self.escape(string)
  string.gsub(/[\(\)\|\-!@~\/"\/\^\$\\]/) { |match| "\\#{match}" }
end

Note that &, =, and < are all escaped by the official PHP version, but not by Riddle's version. The extended query syntax documentation for Sphinx indicates that = may be used as an exact form modifier, and < is used as part of the strict order operator. I'm not sure how & is used, since it doesn't seem to be referenced on that page.

Is the omission of these characters from the escaping logic intentional, or does it represent a bug?

sphinx 2.0.4 with multi_64 attributes problem

when there's multi_64 attributes, riddle get following problem:

{NoMethodError: undefined method `unpack' for nil:NilClass
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.1.3/lib/active_support/whiny_nil.rb:48:in `method_missing'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client/response.rb:26:in `next_int'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client/response.rb:17:in `next'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:837:in `attribute_from_type'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:270:in `block (3 levels) in run'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:269:in `each'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:269:in `block (2 levels) in run'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:263:in `each'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:263:in `map'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:263:in `block in run'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:228:in `collect'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:228:in `run'
from /usr/local/Cellar/ruby/1.9.2-p290/lib/ruby/gems/1.9.1/gems/riddle-1.5.1/lib/riddle/client.rb:341:in `query'

Failover

Riddle will retry the same server 5 times when it encounters an error, but it is not possible to configure it to fail over to a second server in the event of an error.

This would be a useful feature for applications that want to eliminate searchd as a single point of failure. It would be nice if Riddle handled this to avoid having to run an additional Haproxy or similar service.

Preserving original text on snippets

This issue is somewhat a continuation of #63

Basically, i think the Riddle::Query.snippets function should preserve the original text sent to it (except for adding the <span class="match"> tags of course).

For example, these couple of specs added to the spec/functional/escaping_spec.rb would not pass:

  def snippets_for(text)
    res = connection.query Riddle::Query.snippets(text, 'people', '')
    res.first['snippet']
  end

  [
    'email: [email protected]',
    'the files are on C:\\foo\\bar'
  ].each do |text|
    it 'preserves original text on snippets' do
      snippets_for(text).should == text
    end
  end

The rspec output:

Failures:

  1) SphinxQL escaping preserves original text on snippets
     Failure/Error: non_matching_snippet(text).should == text
       expected: "email: [email protected]"
            got: "email: john\\@example.com" (using ==)
     # ./spec/functional/escaping_spec.rb:28:in `block (3 levels) in <top (required)>'

  2) SphinxQL escaping preserves original text on snippets
     Failure/Error: non_matching_snippet(text).should == text
       expected: "the files are on C:\\foo\\bar"
            got: "the files are on C:foobar" (using ==)
     # ./spec/functional/escaping_spec.rb:28:in `block (3 levels) in <top (required)>'

I don't think the examples are too far fetched, and they could certainly be part of a user-generated field on a DB (and the "excerpts" functionality of ThinkingSphinx will forward whatever some ActiveRecord attribute has to the Riddle::Query.snippets function).

I think the root of the problem is treating the to-be-excerpted text as SphinxQL when the CALL SNIPPETS function will not care about special SphinxQL characters (it will treat the data just as normal text as far as i know).

I'd propose to distinguish where the strings are interpreted as normal SQL strings on Sphinx calls, and apply only the Mysql2::Client.escape function in those cases.

Riddle escape not working

Im using:

gem 'riddle', github: 'pat/riddle' , ref: 'c1f8824ae9'
gem 'mysql2', '~> 0.3.12b5'

And TS3.
I get this error:

Mysql2::Error: index game_core,game_delta: query error: no field 'terraria' found in schema

The search term is: "@Terraria"
Here is the relevant stack trace:

vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/connection.rb:58:in `query'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/connection.rb:58:in `query_all'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search/batch_inquirer.rb:16:in `results'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/middlewares/inquirer.rb:9:in `block in call'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/notifications.rb:123:in `block in instrument'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/notifications.rb:123:in `instrument'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search/context.rb:22:in `log'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/middlewares/inquirer.rb:8:in `call'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/middlewares/geographer.rb:9:in `call'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/middlewares/sphinxql.rb:11:in `call'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/middlewares/stale_id_filter.rb:10:in `call'
vendor/bundle/ruby/1.9.1/gems/middleware-0.1.0/lib/middleware/runner.rb:31:in `call'
vendor/bundle/ruby/1.9.1/gems/middleware-0.1.0/lib/middleware/builder.rb:102:in `call'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search.rb:58:in `populate'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search.rb:38:in `meta'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/masks/pagination_mask.rb:42:in `total_entries'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search.rb:96:in `block in method_missing'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search.rb:95:in `each'
vendor/bundle/ruby/1.9.1/gems/thinking-sphinx-3.0.0/lib/thinking_sphinx/search.rb:95:in `method_missing'

The code is simple:

ThinkingSphinx.search Riddle.escape(@search_term), options

I hope I put this at the right place if so I can create a new one in the TS issue tracker.

Ruby 1.9.x encoding issue

Riddle returns all values with Encoding::ASCII_8BIT with ruby 1.9.x.
I think this behavior is incorrect. Riddle should respect Encoding.default_external or specify encoding other way.

Connect to unix socket

There doesn't seem to be a way to connect to a searchd unix socket which is supported since 0.9.9?

Avoiding select star

Hi,

This isn't a huge issue, but I noticed that it's basically impossible to NOT pull back star when doing a select: https://github.com/pat/riddle/blob/master/lib/riddle/query/select.rb#L3

@values is initiated with * and there is no way to skip. Thinking Sphinx seems to be affected by this in that most queries end up with an extra set of columns. I doubt this has a huge impact, but I must assume that it means that more data is sent over the line, resulting in some performance penalty.

auto version detection fail

Hello,

This is information for anyone who's having trouble deploying their rails app with passenger and ruby 1.9. This concerns using passenger, centos5, ruby 1.9, sphinx and the riddle gems together.

For some reason ruby 1.8 auto detects version fine, however, deploying via passenger and ruby 1.9, auto detection fails and the app doesn't deploy. The problem was in file
.../shared/bundle/ruby/1.9.1/gems/riddle-1.3.0/lib/riddle/auto_version.rb
line 15 which issues an exit command.

I had to replace the exit statement with a 'require' for my version of sphinx -- lines surrounding line 15:

...
else
  puts "found version: #{version}"
  #exit
  require "riddle/0.9.9"
end
...

The above change allowed a deploy.

-Cheers!

escaping ^

Hi,

I'm not really sure why but it seems that ^ need to be escape twice in some case.
If you search the result of Riddle.escape("abc^") you will get a sphinx error unexpected $end, expecting TOK_KEYWORD or TOK_INT near ''

But searching for Riddle.escape("abc ^") does not throw any error.

How to update and insert new data through Riddle

Hi Pat,

Our current setup consists of the following dance:

  1. Once a day, generate loads of XML of updated content.
  2. Rotate the indexes.

We want to make this a bit more agile, and with the new version of Riddle I seem to have a few options for this, but I can't figure out exactly how it works.

Updating existing content is easy, I just call:
riddle_client.update(index_name, changed_attributes, {content.id => new_values })

But how do I handle new content nicely?
I understand I can go the XML path again, but I'd rather do something like thinking-sphinx where I insert new content in a delta index and call an index merge through Riddle. Could you point me in the right direction for this?

Problem loading fixtures

/Users/jamescook/work/riddle/spec/sphinx_helper.rb:39:in `query': The used command is not allowed with this MySQL version (Mysql2::Error)

The below tweak makes it behave. I'm running mysql Ver 14.14 Distrib 5.5.10, for osx10.5 (i386) using EditLine wrapper

@@ -37,7 +37,7 @@ class SphinxHelper
structure = File.open("spec/fixtures/sql/structure.sql") { |f| f.read }
structure.split(/;/).each { |sql| client.query sql }
client.query <<-SQL

  •  LOAD DATA LOCAL INFILE '#{@path}/fixtures/sql/data.tsv' INTO TABLE
    
  •  LOAD DATA INFILE '#{@path}/fixtures/sql/data.tsv' INTO TABLE
    
    riddle.people FIELDS TERMINATED BY ',' ENCLOSED BY "'" (gender,
    first_name, middle_initial, last_name, street_address, city, state,
    postcode, email, birthday)

Failover not working

As of 40c96fd, failover no longer work.

initialise_socket uses server which pulls from @servers.first which will not change because servers.dup is happening.

SPH_RANK_EXPR missing in RankModes

Hi,
Thanks for your wonderful gems. I am using them on the latest version of sphinx 2.0.3.
Probably it is just work in progress : found SPH_RANK_EXPR missing in RankModes.
Regards,
Miguel

Query is hanging and won't timeout

Be forewarned: this is not a well-defined issue, as I don't yet have the experience I need to do a better job defining it... sorry for that. If there's a more appropriate place to post this, please let me know :)

We are using Riddle in a Rails 3 project which is running on Passenger Standalone in production. Sphinx is running on its own server. Occasionally (maybe once every hour or two) we will get a hanging worker process (rack/ruby), which we have to kill manually, and if we wait too long, these hung processes will take-over the entire worker pool and the app will stop responding.

I have killed the process (kill -SIGABRT) to get a stack trace and find out where they are hanging, and every single one I've killed so far has been on this line:

result = client.query(query)

where client is, of course, a Riddle::Client. This is currently in the code a bit further up:

client.timeout = 8
client.max_query_time = 200
client.retry_count = 3
client.retry_delay = 100

But even with that, the processes are hanging on that same line.

At first I thought perhaps it was an issue with Passenger forking, and causing Riddle to use the same file descriptor as a connection/socket for two separate processes, but we actually initialize a new Riddle::Client on every call to the method containing the above code, so I don't see how that could be it.

I guess what I'm curious about is the fact that, from looking at the code in client.request, I don't see it using a Timeout anywhere. I assume that's where it's hanging (although I'm not sure how to tell), but from what I can tell the timeout only applies to the connect phase of the process. If that's the case is it possible to make the timeout apply to the whole query rather than just the connection?

Or is there some way I can get more specific information about where it's hanging that would be more useful? Thanks!

Riddle gives broken results, while SphinxQL gives correct results for same query.

My entire endeavor can be read here: http://sphinxsearch.com/forum/view.html?id=9422, but the gist is this:

If I do this:

client = Riddle::Client.new
client.match_mode = :extended2
client.rank_mode = :bm25
client.group_by = 'group_by_id'
client.group_function = :attr
client.index_weights = {"content_stemmer" => 7, "content_metaphone" => 10,"content_soundex" => 3}
client.field_weights = {'title' => 10, 'artist' => 10, 'description' => 5, 'search_words'=> 5}
client.sort_mode = :extended
client.sort_by = '@weight DESC'
results = client.query("test")

I does nothing with the query. Instead I get the top 20 of all my documents sorted by document id, however if I do the same in SphinxQL:

SELECT content_id,class_id,group_by_id
FROM content_stemmer,content_metaphone,content_soundex
WHERE MATCH('test')
GROUP BY group_by_id 
ORDER BY @weight DESC
OPTION field_weights=(title=10, artist=10, description=5, search_words=5),
    index_weights=(content_stemmer=7,content_soundex=3,content_metaphone=10), ranker=bm25;

I get correct and nicely weighted results. Either I am using Riddle incorrectly or I hit a bug.

Errno::ETIMEDOUT should re-raise Riddle::ConnectionError

I received the following error on production. It has never happened before, so probably the occurrence might be an edge case under a high load.

Errno::ETIMEDOUT: Connection timed out - connect(2)
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:572:in `initialize'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:572:in `new'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:572:in `initialise_socket'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/0.9.9/client.rb:8:in `initialise_connection'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:498:in `open_socket'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:535:in `connect'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:624:in `request'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:226:in `run'
[GEM_ROOT]/gems/riddle-1.3.3/lib/riddle/client.rb:338:in `query'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:397:in `block (2 levels) in populate'
[GEM_ROOT]/gems/activesupport-3.0.9/lib/active_support/notifications.rb:52:in `block in instrument'
[GEM_ROOT]/gems/activesupport-3.0.9/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
[GEM_ROOT]/gems/activesupport-3.0.9/lib/active_support/notifications.rb:52:in `instrument'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:501:in `log'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:510:in `log'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:396:in `block in populate'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:551:in `call'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:551:in `retry_on_stale_index'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:394:in `populate'
[GEM_ROOT]/gems/thinking-sphinx-2.0.5/lib/thinking_sphinx/search.rb:176:in `method_missing'
app/controllers/api/user_controller.rb:72:in `search'

Riddle::Client#initialise_socket has a rescue Errno::ECONNREFUSED block and retries 5 times when TCPSocket.new server, @port raises that error, then re-raise Riddle::ConnectionError. I think Errno::ETIMEDOUT should be handled in the same manner.

Along the same line, Errno::ECONNRESET could happen if sphinx is killed or crashed and restarted in the middle of a query, however I've never experienced it yet.

In the app code level, it'd be nice if I could just write rescue Riddle::ConnectionError to catch everything related to, well, connection error.

On a side note, I'm not sure if retrying 5 times is a good idea - in the Errno::ECONNREFUSED case, it usually means sphinx is not up and running yet, and those refused packets are returned immediately, which means 5 times retry might occur in 0.5-1.0ms depending on your network latency and it's unlikely that waiting for 1.0ms helps. But I might be wrong - if the code came from the real experience. In the Errno::ETIMEDOUT case, it makes a bit more sense, as timeout means by the time the error is raised it waited for some time and creates meaningful retry interval. But, it also means that the process / thread is blocked for a 5 times longer period.

Probably, raising Riddle::ConnectionError immediately in any above case without a retry may be a better default behavior?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.