picky 0.0.0 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/picky +14 -0
- data/lib/bundling.rb +10 -0
- data/lib/constants.rb +9 -0
- data/lib/deployment.rb +212 -0
- data/lib/picky/application.rb +40 -0
- data/lib/picky/cacher/convenience.rb +3 -0
- data/lib/picky/cacher/generator.rb +17 -0
- data/lib/picky/cacher/partial/default.rb +7 -0
- data/lib/picky/cacher/partial/none.rb +19 -0
- data/lib/picky/cacher/partial/strategy.rb +7 -0
- data/lib/picky/cacher/partial/subtoken.rb +91 -0
- data/lib/picky/cacher/partial_generator.rb +15 -0
- data/lib/picky/cacher/similarity/default.rb +7 -0
- data/lib/picky/cacher/similarity/double_levenshtone.rb +73 -0
- data/lib/picky/cacher/similarity/none.rb +25 -0
- data/lib/picky/cacher/similarity/strategy.rb +7 -0
- data/lib/picky/cacher/similarity_generator.rb +15 -0
- data/lib/picky/cacher/weights/default.rb +7 -0
- data/lib/picky/cacher/weights/logarithmic.rb +39 -0
- data/lib/picky/cacher/weights/strategy.rb +7 -0
- data/lib/picky/cacher/weights_generator.rb +15 -0
- data/lib/picky/configuration/configuration.rb +13 -0
- data/lib/picky/configuration/field.rb +68 -0
- data/lib/picky/configuration/indexes.rb +60 -0
- data/lib/picky/configuration/queries.rb +32 -0
- data/lib/picky/configuration/type.rb +52 -0
- data/lib/picky/cores.rb +101 -0
- data/lib/picky/db/configuration.rb +23 -0
- data/lib/picky/ext/ruby19/extconf.rb +7 -0
- data/lib/picky/ext/ruby19/performant.c +339 -0
- data/lib/picky/extensions/array.rb +45 -0
- data/lib/picky/extensions/hash.rb +11 -0
- data/lib/picky/extensions/module.rb +15 -0
- data/lib/picky/extensions/symbol.rb +18 -0
- data/lib/picky/generator.rb +156 -0
- data/lib/picky/helpers/cache.rb +23 -0
- data/lib/picky/helpers/gc.rb +11 -0
- data/lib/picky/helpers/measuring.rb +45 -0
- data/lib/picky/helpers/search.rb +27 -0
- data/lib/picky/index/bundle.rb +328 -0
- data/lib/picky/index/category.rb +109 -0
- data/lib/picky/index/combined.rb +38 -0
- data/lib/picky/index/type.rb +30 -0
- data/lib/picky/indexers/base.rb +77 -0
- data/lib/picky/indexers/default.rb +3 -0
- data/lib/picky/indexers/field.rb +13 -0
- data/lib/picky/indexers/no_source_specified_error.rb +5 -0
- data/lib/picky/indexers/solr.rb +60 -0
- data/lib/picky/indexes.rb +180 -0
- data/lib/picky/initializers/ext.rb +6 -0
- data/lib/picky/initializers/mysql.rb +22 -0
- data/lib/picky/loader.rb +287 -0
- data/lib/picky/loggers/search.rb +19 -0
- data/lib/picky/performant/array.rb +23 -0
- data/lib/picky/query/allocation.rb +82 -0
- data/lib/picky/query/allocations.rb +131 -0
- data/lib/picky/query/base.rb +124 -0
- data/lib/picky/query/combination.rb +69 -0
- data/lib/picky/query/combinations.rb +106 -0
- data/lib/picky/query/combinator.rb +92 -0
- data/lib/picky/query/full.rb +15 -0
- data/lib/picky/query/live.rb +22 -0
- data/lib/picky/query/qualifiers.rb +73 -0
- data/lib/picky/query/solr.rb +77 -0
- data/lib/picky/query/token.rb +215 -0
- data/lib/picky/query/tokens.rb +102 -0
- data/lib/picky/query/weigher.rb +159 -0
- data/lib/picky/query/weights.rb +55 -0
- data/lib/picky/rack/harakiri.rb +37 -0
- data/lib/picky/results/base.rb +103 -0
- data/lib/picky/results/full.rb +19 -0
- data/lib/picky/results/live.rb +19 -0
- data/lib/picky/routing.rb +165 -0
- data/lib/picky/signals.rb +11 -0
- data/lib/picky/solr/schema_generator.rb +73 -0
- data/lib/picky/sources/base.rb +19 -0
- data/lib/picky/sources/csv.rb +30 -0
- data/lib/picky/sources/db.rb +77 -0
- data/lib/picky/tokenizers/base.rb +130 -0
- data/lib/picky/tokenizers/default.rb +3 -0
- data/lib/picky/tokenizers/index.rb +73 -0
- data/lib/picky/tokenizers/query.rb +70 -0
- data/lib/picky/umlaut_substituter.rb +21 -0
- data/lib/picky-tasks.rb +6 -0
- data/lib/picky.rb +18 -0
- data/lib/tasks/application.rake +5 -0
- data/lib/tasks/cache.rake +53 -0
- data/lib/tasks/framework.rake +4 -0
- data/lib/tasks/index.rake +29 -0
- data/lib/tasks/server.rake +48 -0
- data/lib/tasks/shortcuts.rake +13 -0
- data/lib/tasks/solr.rake +36 -0
- data/lib/tasks/spec.rake +11 -0
- data/lib/tasks/statistics.rake +13 -0
- data/lib/tasks/try.rake +29 -0
- data/prototype_project/Gemfile +23 -0
- data/prototype_project/Rakefile +1 -0
- data/prototype_project/app/README +6 -0
- data/prototype_project/app/application.rb +50 -0
- data/prototype_project/app/application.ru +29 -0
- data/prototype_project/app/db.yml +10 -0
- data/prototype_project/app/logging.rb +20 -0
- data/prototype_project/app/unicorn.ru +10 -0
- data/prototype_project/log/README +1 -0
- data/prototype_project/script/console +34 -0
- data/prototype_project/tmp/README +0 -0
- data/prototype_project/tmp/pids/README +0 -0
- data/spec/ext/performant_spec.rb +64 -0
- data/spec/lib/application_spec.rb +61 -0
- data/spec/lib/cacher/partial/subtoken_spec.rb +89 -0
- data/spec/lib/cacher/partial_generator_spec.rb +35 -0
- data/spec/lib/cacher/similarity/double_levenshtone_spec.rb +60 -0
- data/spec/lib/cacher/similarity/none_spec.rb +23 -0
- data/spec/lib/cacher/similarity_generator_spec.rb +22 -0
- data/spec/lib/cacher/weights/logarithmic_spec.rb +30 -0
- data/spec/lib/cacher/weights_generator_spec.rb +21 -0
- data/spec/lib/configuration/configuration_spec.rb +38 -0
- data/spec/lib/configuration/type_spec.rb +49 -0
- data/spec/lib/configuration_spec.rb +8 -0
- data/spec/lib/cores_spec.rb +65 -0
- data/spec/lib/extensions/array_spec.rb +37 -0
- data/spec/lib/extensions/hash_spec.rb +11 -0
- data/spec/lib/extensions/module_spec.rb +27 -0
- data/spec/lib/extensions/symbol_spec.rb +85 -0
- data/spec/lib/generator_spec.rb +135 -0
- data/spec/lib/helpers/cache_spec.rb +35 -0
- data/spec/lib/helpers/gc_spec.rb +71 -0
- data/spec/lib/helpers/measuring_spec.rb +18 -0
- data/spec/lib/helpers/search_spec.rb +50 -0
- data/spec/lib/index/bundle_partial_generation_speed_spec.rb +47 -0
- data/spec/lib/index/bundle_spec.rb +260 -0
- data/spec/lib/index/category_spec.rb +203 -0
- data/spec/lib/indexers/base_spec.rb +73 -0
- data/spec/lib/indexers/field_spec.rb +20 -0
- data/spec/lib/loader_spec.rb +48 -0
- data/spec/lib/loggers/search_spec.rb +19 -0
- data/spec/lib/performant/array_spec.rb +13 -0
- data/spec/lib/query/allocation_spec.rb +194 -0
- data/spec/lib/query/allocations_spec.rb +336 -0
- data/spec/lib/query/base_spec.rb +104 -0
- data/spec/lib/query/combination_spec.rb +90 -0
- data/spec/lib/query/combinations_spec.rb +83 -0
- data/spec/lib/query/combinator_spec.rb +112 -0
- data/spec/lib/query/full_spec.rb +22 -0
- data/spec/lib/query/live_spec.rb +61 -0
- data/spec/lib/query/qualifiers_spec.rb +31 -0
- data/spec/lib/query/solr_spec.rb +51 -0
- data/spec/lib/query/token_spec.rb +297 -0
- data/spec/lib/query/tokens_spec.rb +189 -0
- data/spec/lib/query/weights_spec.rb +47 -0
- data/spec/lib/results/base_spec.rb +233 -0
- data/spec/lib/routing_spec.rb +318 -0
- data/spec/lib/solr/schema_generator_spec.rb +42 -0
- data/spec/lib/sources/db_spec.rb +91 -0
- data/spec/lib/tokenizers/base_spec.rb +61 -0
- data/spec/lib/tokenizers/index_spec.rb +51 -0
- data/spec/lib/tokenizers/query_spec.rb +105 -0
- data/spec/lib/umlaut_substituter_spec.rb +84 -0
- data/spec/specific/speed_spec.rb +55 -0
- metadata +371 -15
- data/README.textile +0 -9
@@ -0,0 +1,109 @@
|
|
1
|
+
module Index
|
2
|
+
|
3
|
+
# An index category holds a full and a partial index for a given field.
|
4
|
+
#
|
5
|
+
# For example an index category for names holds a full and
|
6
|
+
# a partial index bundle for names.
|
7
|
+
#
|
8
|
+
class Category
|
9
|
+
|
10
|
+
attr_reader :name, :type, :full, :partial
|
11
|
+
|
12
|
+
#
|
13
|
+
#
|
14
|
+
def initialize name, type, options = {}
|
15
|
+
@name = name
|
16
|
+
@type = type
|
17
|
+
|
18
|
+
partial = options[:partial] || Cacher::Partial::Default
|
19
|
+
weights = options[:weights] || Cacher::Weights::Default
|
20
|
+
similarity = options[:similarity] || Cacher::Similarity::Default
|
21
|
+
|
22
|
+
@full = options[:full_bundle] || Bundle.new(:full, self, type, Cacher::Partial::None.new, weights, similarity)
|
23
|
+
@partial = options[:partial_bundle] || Bundle.new(:partial, self, type, partial, weights, Cacher::Similarity::None.new)
|
24
|
+
|
25
|
+
@full = options[:full_lambda].call(@full, @partial) if options[:full_lambda]
|
26
|
+
@partial = options[:partial_lambda].call(@full, @partial) if options[:partial_lambda]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Loads the index from cache.
|
30
|
+
#
|
31
|
+
def load_from_cache
|
32
|
+
full.load
|
33
|
+
partial.load
|
34
|
+
end
|
35
|
+
|
36
|
+
def identifier
|
37
|
+
"#{type.name}:#{name}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Generates all caches for this category.
|
41
|
+
#
|
42
|
+
def generate_caches
|
43
|
+
exclaim "#{Time.now}: Loading data from db for #{identifier}."
|
44
|
+
generate_caches_from_db
|
45
|
+
exclaim "#{Time.now}: Generating partial for #{identifier}."
|
46
|
+
generate_partial
|
47
|
+
exclaim "#{Time.now}: Generating caches from memory for #{identifier}."
|
48
|
+
generate_caches_from_memory
|
49
|
+
exclaim "#{Time.now}: Dumping all caches for #{identifier}."
|
50
|
+
dump_caches
|
51
|
+
end
|
52
|
+
def generate_caches_from_db
|
53
|
+
full.generate_caches_from_db
|
54
|
+
end
|
55
|
+
def generate_partial
|
56
|
+
partial.generate_partial_from full.index
|
57
|
+
end
|
58
|
+
def generate_caches_from_memory
|
59
|
+
partial.generate_caches_from_memory
|
60
|
+
end
|
61
|
+
def dump_caches
|
62
|
+
full.dump
|
63
|
+
partial.dump
|
64
|
+
end
|
65
|
+
def exclaim text
|
66
|
+
puts text
|
67
|
+
end
|
68
|
+
|
69
|
+
# Used for testing.
|
70
|
+
#
|
71
|
+
def generate_indexes_from_full_index
|
72
|
+
generate_derived_full
|
73
|
+
generate_partial
|
74
|
+
generate_derived_partial
|
75
|
+
end
|
76
|
+
def generate_derived_full
|
77
|
+
full.generate_derived
|
78
|
+
end
|
79
|
+
def generate_derived_partial
|
80
|
+
partial.generate_derived
|
81
|
+
end
|
82
|
+
|
83
|
+
# Gets the weight for this token's text.
|
84
|
+
#
|
85
|
+
def weight token
|
86
|
+
bundle_for(token).weight token.text
|
87
|
+
end
|
88
|
+
|
89
|
+
# Gets the ids for this token's text.
|
90
|
+
#
|
91
|
+
def ids token
|
92
|
+
bundle_for(token).ids token.text
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns the right index bundle for this token.
|
96
|
+
#
|
97
|
+
def bundle_for token
|
98
|
+
token.partial? ? partial : full
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
#
|
103
|
+
def combination_for token
|
104
|
+
weight(token) && ::Query::Combination.new(token, self)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
module Index
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
class Combined < Bundle
|
8
|
+
|
9
|
+
delegate :similar,
|
10
|
+
:identifier,
|
11
|
+
:name,
|
12
|
+
:to => :@full
|
13
|
+
delegate :type,
|
14
|
+
:category,
|
15
|
+
:weight,
|
16
|
+
:generate_partial_from,
|
17
|
+
:generate_caches_from_memory,
|
18
|
+
:generate_derived,
|
19
|
+
:dump,
|
20
|
+
:load,
|
21
|
+
:to => :@partial
|
22
|
+
|
23
|
+
def initialize full, partial
|
24
|
+
@full = full
|
25
|
+
@partial = partial
|
26
|
+
end
|
27
|
+
|
28
|
+
def ids text
|
29
|
+
@full.ids(text) + @partial.ids(text)
|
30
|
+
end
|
31
|
+
|
32
|
+
def weight text
|
33
|
+
[@full.weight(text) || 0, @partial.weight(text) || 0].max
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Index
|
2
|
+
|
3
|
+
# This class is for multiple types.
|
4
|
+
#
|
5
|
+
# For example, you could have types books, isbn.
|
6
|
+
#
|
7
|
+
class Type
|
8
|
+
|
9
|
+
attr_reader :name, :result_type, :categories, :combinator
|
10
|
+
|
11
|
+
each_delegate :generate_caches, :load_from_cache, :to => :categories
|
12
|
+
|
13
|
+
# TODO Use config
|
14
|
+
#
|
15
|
+
def initialize name, result_type, ignore_unassigned_tokens, *categories
|
16
|
+
@name = name
|
17
|
+
@result_type = result_type # TODO Move.
|
18
|
+
@categories = categories # for each_delegate
|
19
|
+
@combinator = Query::Combinator.new @categories, :ignore_unassigned_tokens => ignore_unassigned_tokens # TODO pass this in?
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
#
|
24
|
+
def possible_combinations token
|
25
|
+
@combinator.possible_combinations_for token
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Indexers
|
3
|
+
# Indexer.
|
4
|
+
#
|
5
|
+
# 1. Gets data from the original table and copies it into a "snapshot table".
|
6
|
+
# 3. Processes the data. I.e. takes the snapshot table data words and tokenizes etc. them. Writes the result into a txt file.
|
7
|
+
#
|
8
|
+
class Base
|
9
|
+
|
10
|
+
def initialize type, field
|
11
|
+
@type = type
|
12
|
+
@field = field
|
13
|
+
end
|
14
|
+
|
15
|
+
# Convenience method for getting the right Tokenizer.
|
16
|
+
#
|
17
|
+
def tokenizer
|
18
|
+
@field.tokenizer
|
19
|
+
end
|
20
|
+
# Convenience methods for user subclasses.
|
21
|
+
#
|
22
|
+
def search_index_file_name
|
23
|
+
@field.search_index_file_name
|
24
|
+
end
|
25
|
+
|
26
|
+
# Executes the specific strategy.
|
27
|
+
#
|
28
|
+
def index
|
29
|
+
process
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get the source where the data is taken from.
|
33
|
+
#
|
34
|
+
def source
|
35
|
+
@field.source || raise_no_source
|
36
|
+
end
|
37
|
+
def raise_no_source
|
38
|
+
raise NoSourceSpecifiedException.new "No source given for #{@type.name}:#{@field.name}."
|
39
|
+
end
|
40
|
+
|
41
|
+
# Selects the original id (indexed id) and a column to process. The column data is called "token".
|
42
|
+
#
|
43
|
+
def process
|
44
|
+
comma = ?,
|
45
|
+
newline = ?\n
|
46
|
+
|
47
|
+
File.open(search_index_file_name, 'w:binary') do |file|
|
48
|
+
chunked do |indexed_id, text|
|
49
|
+
tokenizer.tokenize(text).each do |token_text|
|
50
|
+
file.write indexed_id
|
51
|
+
file.write comma
|
52
|
+
file.write token_text
|
53
|
+
file.write newline
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
# Split original data into chunks.
|
59
|
+
#
|
60
|
+
def chunked
|
61
|
+
(0..source.count(@type)).step(chunksize) do |offset|
|
62
|
+
indexing_message offset
|
63
|
+
data = source.harvest @type, @field, offset, chunksize
|
64
|
+
data.each do |indexed_id, text|
|
65
|
+
next unless text
|
66
|
+
text.force_encoding 'utf-8' # TODO Still needed?
|
67
|
+
yield indexed_id, text
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def indexing_message offset
|
73
|
+
puts "#{Time.now}: Indexing #{@type.name}:#{@field.name}:#{@field.indexed_name} beginning at #{offset}."
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'rsolr'
|
4
|
+
module Indexers
|
5
|
+
# This is an indexer in its own right.
|
6
|
+
#
|
7
|
+
# TODO Perhaps merge with the existing indexer.
|
8
|
+
#
|
9
|
+
class Solr
|
10
|
+
|
11
|
+
attr_reader :type, :fields, :solr
|
12
|
+
|
13
|
+
# Takes a Configuration::Type.
|
14
|
+
#
|
15
|
+
def initialize type
|
16
|
+
@type = type
|
17
|
+
@fields = type.solr_fields.map(&:name).map(&:to_sym)
|
18
|
+
@solr = RSolr.connect
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO Rewrite such that it works in batches.
|
22
|
+
#
|
23
|
+
def index
|
24
|
+
puts "#{Time.now}: Indexing solr for #{type.name}:#{fields.join(', ')}"
|
25
|
+
statement = "SELECT indexed_id, #{fields.join(',')} FROM #{type.snapshot_table_name}"
|
26
|
+
|
27
|
+
# TODO Rewrite.
|
28
|
+
#
|
29
|
+
DB.connect
|
30
|
+
results = DB.connection.execute statement
|
31
|
+
|
32
|
+
return unless results # TODO check
|
33
|
+
|
34
|
+
type_name = @type.name.to_s
|
35
|
+
|
36
|
+
solr.delete_by_query "type:#{type_name}"
|
37
|
+
solr.commit
|
38
|
+
|
39
|
+
documents = []
|
40
|
+
|
41
|
+
results.each do |indexed_id, *values|
|
42
|
+
values.each &:downcase!
|
43
|
+
documents << hashed(values).merge(:id => indexed_id, :type => type_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
solr.add documents
|
47
|
+
solr.commit
|
48
|
+
solr.optimize
|
49
|
+
end
|
50
|
+
|
51
|
+
def hashed values
|
52
|
+
result = {}
|
53
|
+
fields.zip(values).each do |field, value|
|
54
|
+
result[field] = value
|
55
|
+
end
|
56
|
+
result
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
module Indexes
|
2
|
+
|
3
|
+
mattr_accessor :configuration, :types, :type_mapping
|
4
|
+
|
5
|
+
# Takes a snapshot of the originating table.
|
6
|
+
#
|
7
|
+
def self.take_snapshot *args
|
8
|
+
configuration.take_snapshot *args
|
9
|
+
end
|
10
|
+
# Runs the indexers in parallel (index + cache).
|
11
|
+
#
|
12
|
+
def self.index
|
13
|
+
Indexes.take_snapshot
|
14
|
+
|
15
|
+
# Run in parallel.
|
16
|
+
#
|
17
|
+
puts "Indexing using #{Cores.max_processors} processors."
|
18
|
+
Cores.forked self.fields, :randomly => true do |field|
|
19
|
+
# Reestablish DB connection.
|
20
|
+
DB.connect # TODO Rewrite!
|
21
|
+
field.index
|
22
|
+
field.cache
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def self.index_solr
|
26
|
+
configuration.index_solr
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns an array of fields.
|
30
|
+
#
|
31
|
+
# TODO Rewrite.
|
32
|
+
#
|
33
|
+
def self.fields
|
34
|
+
result = []
|
35
|
+
configuration.types.each do |type|
|
36
|
+
type.fields.inject(result) do |total, field|
|
37
|
+
total << field
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
#
|
45
|
+
# TODO Rewrite.
|
46
|
+
#
|
47
|
+
def self.find type_name, field_name
|
48
|
+
type_name = type_name.to_sym
|
49
|
+
field_name = field_name.to_sym
|
50
|
+
configuration.types.each do |type|
|
51
|
+
next unless type.name == type_name
|
52
|
+
type.fields.each do |field|
|
53
|
+
next unless field.name == field_name
|
54
|
+
return field
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Backup / Restore.
|
60
|
+
#
|
61
|
+
def self.backup_caches
|
62
|
+
each_category do |category|
|
63
|
+
category.full.backup
|
64
|
+
category.partial.backup
|
65
|
+
end
|
66
|
+
end
|
67
|
+
def self.restore_caches
|
68
|
+
each_category do |category|
|
69
|
+
category.full.restore
|
70
|
+
category.partial.restore
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Use these if you need to index / cache a single index.
|
75
|
+
#
|
76
|
+
def self.generate_index_only type_name, field_name
|
77
|
+
Indexes.configuration.types.each do |type|
|
78
|
+
next unless type_name == type.name
|
79
|
+
type.fields.each do |field|
|
80
|
+
field.index if field_name == field.name
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
def self.generate_cache_only type_name, category_name
|
85
|
+
Indexes.each do |type|
|
86
|
+
next unless type_name == type.name
|
87
|
+
type.categories.each do |category|
|
88
|
+
category.generate_caches if category_name == category.name
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Runs the index cache generation.
|
94
|
+
#
|
95
|
+
# TODO Needed?
|
96
|
+
#
|
97
|
+
def self.generate_caches
|
98
|
+
each &:generate_caches
|
99
|
+
end
|
100
|
+
# Loads all indexes from the caches.
|
101
|
+
#
|
102
|
+
def self.load_from_cache
|
103
|
+
each &:load_from_cache
|
104
|
+
end
|
105
|
+
def self.reload
|
106
|
+
load_from_cache
|
107
|
+
end
|
108
|
+
|
109
|
+
# Checks if the caches are there.
|
110
|
+
#
|
111
|
+
def self.check_caches
|
112
|
+
each do |type|
|
113
|
+
type.categories.each do |category|
|
114
|
+
category.full.raise_unless_cache_exists
|
115
|
+
category.partial.raise_unless_cache_exists
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Removes the cache files.
|
121
|
+
#
|
122
|
+
def self.clear_caches
|
123
|
+
each do |type|
|
124
|
+
type.categories.each do |category|
|
125
|
+
category.full.delete_all
|
126
|
+
category.partial.delete_all
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Creates the directory structure for the indexes.
|
132
|
+
#
|
133
|
+
# TODO Should be on type?
|
134
|
+
#
|
135
|
+
def self.create_directory_structure
|
136
|
+
each_bundle do |full, partial|
|
137
|
+
full.create_directory
|
138
|
+
partial.create_directory
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
#
|
144
|
+
def self.clear
|
145
|
+
self.types = []
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def self.each &block
|
150
|
+
types.each &block
|
151
|
+
end
|
152
|
+
def self.each_category &block
|
153
|
+
each do |type|
|
154
|
+
type.categories.each &block
|
155
|
+
end
|
156
|
+
end
|
157
|
+
def self.each_bundle
|
158
|
+
each_category do |category|
|
159
|
+
yield category.full, category.partial
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Loads all index definitions.
|
164
|
+
#
|
165
|
+
def self.setup
|
166
|
+
self.types ||= []
|
167
|
+
self.type_mapping ||= {}
|
168
|
+
configuration.types.each do |type|
|
169
|
+
add type.generate
|
170
|
+
end
|
171
|
+
end
|
172
|
+
def self.add type
|
173
|
+
self.type_mapping[type.name] = type
|
174
|
+
self.types << type
|
175
|
+
end
|
176
|
+
def self.[] type_name
|
177
|
+
self.type_mapping[type_name]
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Wrapper for the mysql adapter method execute
|
2
|
+
# to handle the 8 hours disconnect problem.
|
3
|
+
# (http://www.mysql.fr/search/?q=autoreconnect)
|
4
|
+
#
|
5
|
+
ActiveRecord::ConnectionAdapters::MysqlAdapter.module_eval do
|
6
|
+
def execute_with_retry_once(sql, name = nil)
|
7
|
+
retried = false
|
8
|
+
begin
|
9
|
+
execute_without_retry_once(sql, name)
|
10
|
+
rescue ActiveRecord::StatementInvalid => statement_invalid_exception
|
11
|
+
# Our database connection has gone away, reconnect and retry this method
|
12
|
+
#
|
13
|
+
reconnect!
|
14
|
+
unless retried
|
15
|
+
retried = true
|
16
|
+
retry
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method_chain :execute, :retry_once
|
22
|
+
end
|