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
# 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
  @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



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

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



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

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



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

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

#process(options = {}) ⇒ Object



88
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
# File 'lib/cloudinary/migrator.rb', line 88

def process(options={})
  raise CloudinaryException, "url not given and no retrieve callback given" if options[:url].nil? && self.retrieve.nil?
  raise CloudinaryException, "id not given and retrieve 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



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

def register_complete(&block)
  @complete = block
end

#register_retrieve(&block) ⇒ Object



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

def register_retrieve(&block)
  @retrieve = block
end

#temporary_file(data, filename) ⇒ Object



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

def temporary_file(data, filename)
  file = 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