Class: ContainerManagementMigration

Inherits:
Object
  • Object
show all
Defined in:
backend/app/lib/container_management_migration.rb

Defined Under Namespace

Classes: MigrationMapper

Constant Summary

MIGRATION_MODELS =

For performance reasons, we’re going to feed the ASpace -> Container Management mapper something that behaves like a JSONModel but isn’t fully realized.

We don’t want to have to pull every field of every record back just to update their instances.

So, this implements just enough of our JSONModels to keep the mapper happy.

{}
MAX_RECORDS_PER_TRANSACTION =
10

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Boolean) already_run?

Returns:

  • (Boolean)


7
8
9
10
11
# File 'backend/app/lib/container_management_migration.rb', line 7

def self.already_run?
    DB.open do |db|
      return  !db[:system_event].where( :title => "CONTAINER_MANAGEMENT_UPGRADE_COMPLETED" ).empty? 
    end
end

Instance Method Details

- (Object) ContainerMigrationModel(model_type)



23
24
25
26
27
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'backend/app/lib/container_management_migration.rb', line 23

def ContainerMigrationModel(model_type)

  MIGRATION_MODELS[model_type] ||= Class.new(JSONModel::JSONModel(model_type)) do

    include JSONModel

    def initialize(record)
      @acting_as = record.class
      @fields = {}

      load_relevant_fields(record)
    end

    def is_a?(clz)
      @acting_as.my_jsonmodel == clz
    end

    def [](key)
      @fields.fetch(key.to_s)
    end

    def create_containers(top_containers_in_this_tree)
      # If our incoming instance records already have their subcontainers created, we won't create them again.
      instances_with_subcontainers = self['instance_ids'].zip(self['instances']).map {|instance_id, instance|
        if instance['sub_container']
          instance_id
        end
      }.compact

      MigrationMapper.new(self, false, top_containers_in_this_tree).call

      self['instance_ids'].zip(self['instances']).map {|instance_id, instance|
        # Create a new subcontainer that links everything up
        if instance['sub_container']

          # This subcontainer was added by the mapping process.  Create it.
          if !instances_with_subcontainers.include?(instance_id)
            SubContainer.create_from_json(JSONModel(:sub_container).from_hash(instance['sub_container']), :instance_id => instance_id)
          end

          # Extract the top container we linked to and return it if we haven't seen it before
          top_container_id = JSONModel(:top_container).id_for(instance['sub_container']['top_container']['ref'])

          if !top_containers_in_this_tree.has_key?(top_container_id)
            TopContainer[top_container_id]
          else
            nil
          end
        end
      }.compact
    end


    private

    def load_relevant_fields(record)
      @fields['uri'] = record.uri

      # Set the fields that are used by the mapper to walk the tree.
      if record.is_a?(ArchivalObject)
        if record.parent_id
          @fields['parent'] = {'ref' => ArchivalObject.uri_for(:archival_object, record.parent_id)}
        end

        if record.root_record_id
          @fields['resource'] = {'ref' => Resource.uri_for(:resource, record.root_record_id)}
        end
      end

      # Find the existing instances and their IDs and load them in as well.
      instance_join_column = record.class.association_reflection(:instance)[:key]

      @fields['instances'] = []
      @fields['instance_ids'] = []
      Instance.filter(instance_join_column => record.id).each do |instance|
        @fields['instances'] << Instance.to_jsonmodel(instance).to_hash(:trusted)
        @fields['instance_ids'] << instance.id
      end
    end
  end
end

- (Object) run



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'backend/app/lib/container_management_migration.rb', line 140

def run

  # just in case....
  if self.class.already_run?
    Log.info("*" * 100 )
    Log.info("*\t\t How did you get here? The container management conversion process has already run, or at least there's log of it in the system_event table.") 
    Log.info("*" * 100 )
    return    
  end
  
  DB.open do |db|
    db[:system_event].insert(:title => "CONTAINER_MANAGEMENT_UPGRADE_STARTED",
                               :time => Time.now)
  end
  
  records_migrated = 0

  Repository.all.each do |repo|
    RequestContext.open(:repo_id => repo.id,
                        :is_high_priority => false,
                        :current_username => "admin") do

      # Migrate accession records
      Accession.filter(:repo_id => repo.id).each do |accession|
        Log.info("Working on Accession #{accession.id} (records migrated: #{records_migrated})")
        records_migrated += 1
        ContainerMigrationModel(:accession).new(accession).create_containers({})
      end

      # Then resources and containers
      Resource.filter(:repo_id => repo.id).each do |resource|
        top_containers_in_this_tree = {}

        records_migrated += 1
        ContainerMigrationModel(:resource).new(resource).create_containers(top_containers_in_this_tree).each do |top_container|
          top_containers_in_this_tree[top_container.id] = top_container
        end

        ao_roots = resource.tree['children']

        ao_roots.each do |ao_root|
          work_queue = [ao_root]

          while !work_queue.empty?

            nodes_for_transaction = []
            while !work_queue.empty?
              nodes_for_transaction << work_queue.shift
              break if nodes_for_transaction.length == MAX_RECORDS_PER_TRANSACTION
            end

            Log.info("Running #{nodes_for_transaction.length} for the next transaction")

            DB.open do
              nodes_for_transaction.each do |node|
                work_queue.concat(node['children'])

                record = ArchivalObject[node['id']]

                Log.info("Working on ArchivalObject #{record.id} (records migrated: #{records_migrated})")

                migration_record = ContainerMigrationModel(:archival_object).new(record)

                migration_record.create_containers(top_containers_in_this_tree).each do |top_container|
                  top_containers_in_this_tree[top_container.id] = top_container
                end

                records_migrated += 1
              end
            end
          end
        end
      end
    end
  end

  DB.open do |db|
    db[:system_event].insert(:title => "CONTAINER_MANAGEMENT_UPGRADE_COMPLETED",
                               :time => Time.now)
  end



end