Class: Cloudinary::Migrator

Inherits:
Object show all
Defined in:
lib/cloudinary/migrator.rb

Overview

Copyright Cloudinary

Constant Summary collapse

@@init =
false

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Migrator

Returns a new instance of Migrator.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/cloudinary/migrator.rb', line 28

def initialize(options={})
  self.class.init
  
  options[:db_file] = "tmp/migration#{$$}.db" if options[:private_database] && !options[:db_file] 
  @dbfile = options[:db_file] || "tmp/migration.db"
  FileUtils.mkdir_p(File.dirname(@dbfile))
  @db = SQLite3::Database.new @dbfile, :results_as_hash=>true
  @retrieve = options[:retrieve]
  @complete = options[:complete]
  @debug = options[:debug] || false
  @ignore_duplicates = options[:ignore_duplicates]
  @threads = [options[:threads] || 10, 100].min
  @threads = 1 if RUBY_VERSION < "1.9"
  @extra_options = {:api_key=>options[:api_key], :api_secret=>options[:api_secret]}
  @delete_after_done = options[:delete_after_done] || options[:private_database]
  @max_processing = @threads * 10
  @in_process = 0
  @work = Queue.new
  @results = Queue.new
  @mutex = Mutex.new
  @db.execute "
    create table if not exists queue (
      id integer primary key,
      internal_id integer,
      public_id text,
      url text,
      metadata text,
      result string,
      status text,
      updated_at integer
    )
  "
  @db.execute "
    create index if not exists status_idx on queue (
      status
    )
  "
  @db.execute "
    create unique index if not exists internal_id_idx on queue (
      internal_id
    )
  "
  @db.execute "
    create unique index if not exists public_id_idx on queue (
      public_id
    )
  "

  if options[:reset_queue]
    @db.execute("delete from queue")
  end
end

Instance Attribute Details

#completeObject (readonly)

Returns the value of attribute complete.



4
5
6
# File 'lib/cloudinary/migrator.rb', line 4

def complete
  @complete
end

#dbObject (readonly)

Returns the value of attribute db.



6
7
8
# File 'lib/cloudinary/migrator.rb', line 6

def db
  @db
end

#extra_optionsObject (readonly)

Returns the value of attribute extra_options.



8
9
10
# File 'lib/cloudinary/migrator.rb', line 8

def extra_options
  @extra_options
end

#in_processObject

Returns the value of attribute in_process.



5
6
7
# File 'lib/cloudinary/migrator.rb', line 5

def in_process
  @in_process
end

#mutexObject (readonly)

Returns the value of attribute mutex.



7
8
9
# File 'lib/cloudinary/migrator.rb', line 7

def mutex
  @mutex
end

#resultsObject (readonly)

Returns the value of attribute results.



7
8
9
# File 'lib/cloudinary/migrator.rb', line 7

def results
  @results
end

#retrieveObject (readonly)

Returns the value of attribute retrieve.



4
5
6
# File 'lib/cloudinary/migrator.rb', line 4

def retrieve
  @retrieve
end

#terminateObject

Returns the value of attribute terminate.



5
6
7
# File 'lib/cloudinary/migrator.rb', line 5

def terminate
  @terminate
end

#workObject (readonly)

Returns the value of attribute work.



7
8
9
# File 'lib/cloudinary/migrator.rb', line 7

def work
  @work
end

Class Method Details

.initObject



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/cloudinary/migrator.rb', line 12

def self.init
  return if @@init
  @@init = true

  begin 
    require 'sqlite3'
  rescue LoadError
    raise "Please add sqlite3 to your Gemfile"    
  end
  require 'tempfile'
end

Instance Method Details

#close_if_needed(file) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/cloudinary/migrator.rb', line 130

def close_if_needed(file)
  if file.nil?
    # Do nothing.
  elsif file.respond_to?(:close!) 
    file.close! 
  elsif file.respond_to?(:close)
    file.close
  end
rescue
  # Ignore errors in closing files
end

#doneObject



116
117
118
119
120
121
122
123
124
# File 'lib/cloudinary/migrator.rb', line 116

def done
  start
  process_all_pending
  @terminate = true
  1.upto(@threads){self.work << nil} # enough objects to release all waiting threads
  @started = false
  @db.close
  File.delete(@dbfile) if @delete_after_done
end

#json_decode(str) ⇒ Object



24
25
26
# File 'lib/cloudinary/migrator.rb', line 24

def json_decode(str)
  Cloudinary::Utils.json_decode(str)
end

#max_given_idObject



126
127
128
# File 'lib/cloudinary/migrator.rb', line 126

def max_given_id
  db.get_first_value("select max(internal_id) from queue").to_i
end

#process(options = {}) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/cloudinary/migrator.rb', line 89

def process(options={})    
  raise CloudinaryException, "url not given and no retieve callback given" if options[:url].nil? && self.retrieve.nil?
  raise CloudinaryException, "id not given and retieve or complete callback given" if options[:id].nil? && (!self.retrieve.nil? || !self.complete.nil?)

  debug("Process: #{options.inspect}")
  start
  process_results    
  wait_for_queue
  options = options.dup
  id = options.delete(:id)
  url = options.delete(:url)
  public_id = options.delete(:public_id)
  row = {
    "internal_id"=>id, 
    "url"=>url, 
    "public_id"=>public_id, 
    "metadata"=>options.to_json,
    "status"=>"processing"      
  }    
  begin
    insert_row(row)
    add_to_work_queue(row)
  rescue SQLite3::ConstraintException
    raise if !@ignore_duplicates
  end
end

#register_complete(&block) ⇒ Object



85
86
87
# File 'lib/cloudinary/migrator.rb', line 85

def register_complete(&block)
  @complete = block
end

#register_retrieve(&block) ⇒ Object



81
82
83
# File 'lib/cloudinary/migrator.rb', line 81

def register_retrieve(&block)
  @retrieve = block
end

#temporary_file(data, filename) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/cloudinary/migrator.rb', line 142

def temporary_file(data, filename)  
  file = RUBY_VERSION == "1.8.7" ? Tempfile.new('cloudinary') : Tempfile.new('cloudinary', :encoding => 'ascii-8bit')
  file.unlink
  file.write(data)
  file.rewind
  # Tempfile return path == nil after unlink, which break rest-client              
  class << file
    attr_accessor :original_filename
    def content_type
      "application/octet-stream"                  
    end
  end
  file.original_filename = filename
  file                  
end