[ARVADOS] created: 9c3904d27dc7d6b6aa5834ff0f5815a8b3685e99

git at public.curoverse.com git at public.curoverse.com
Tue Mar 18 17:11:38 EDT 2014


        at  9c3904d27dc7d6b6aa5834ff0f5815a8b3685e99 (commit)


commit 9c3904d27dc7d6b6aa5834ff0f5815a8b3685e99
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Mar 18 17:11:28 2014 -0400

    * New code to find resolve commit versions and ranges by scanning repositories with "git rev-list".
    * When job "create" is called, it may return a previous job if the job specification (script, version, inputs) matches
    * Provided a "nondeterministic" column to speciy a job should not be reused.
    * Added tests for searching commit ranges and when jobs should be re-used.

diff --git a/services/api/app/controllers/arvados/v1/jobs_controller.rb b/services/api/app/controllers/arvados/v1/jobs_controller.rb
index b7b0e67..062a56e 100644
--- a/services/api/app/controllers/arvados/v1/jobs_controller.rb
+++ b/services/api/app/controllers/arvados/v1/jobs_controller.rb
@@ -5,39 +5,24 @@ class Arvados::V1::JobsController < ApplicationController
   skip_before_filter :find_object_by_uuid, :only => :queue
   skip_before_filter :render_404_if_no_object, :only => :queue
 
-  def index
-    return super unless @where.is_a? Hash
-    want_ancestor = @where[:script_version_descends_from]
-    if want_ancestor
-      # Check for missing commit_ancestor rows, and create them if
-      # possible.
-      @objects.
-        dup.
-        includes(:commit_ancestors). # I wish Rails would let me
-                                     # specify here which
-                                     # commit_ancestors I am
-                                     # interested in.
-        each do |o|
-        if o.commit_ancestors.
-            select { |ca| ca.ancestor == want_ancestor }.
-            empty? and !o.script_version.nil?
-          begin
-            o.commit_ancestors << CommitAncestor.find_or_create_by_descendant_and_ancestor(o.script_version, want_ancestor)
-          rescue
-          end
+  def create
+    puts resource_attrs
+    r = Commit.find_commit_range(current_user,
+                                 resource_attrs[:repository],
+                                 resource_attrs[:minimum_script_version],
+                                 resource_attrs[:script_version])    
+    if !resource_attrs[:nondeterministic]
+      Job.readable_by(current_user).where(script: resource_attrs[:script],
+                                          script_version: r).
+        each do |j|
+        if j.nondeterministic != true and j.success != false and j.script_parameters == resource_attrs[:script_parameters]
+          @object = j
+          return show
         end
-        o.commit_ancestors.
-          select { |ca| ca.ancestor == want_ancestor }.
-          select(&:is).
-          first
       end
-      # Now it is safe to do an .includes().where() because we are no
-      # longer interested in jobs that have other ancestors but not
-      # want_ancestor.
-      @objects = @objects.
-        includes(:commit_ancestors).
-        where('commit_ancestors.ancestor = ? and commit_ancestors.is = ?',
-              want_ancestor, true)
+    end
+    if r
+      resource_attrs[:script_version] = r[0]
     end
     super
   end
diff --git a/services/api/app/controllers/arvados/v1/schema_controller.rb b/services/api/app/controllers/arvados/v1/schema_controller.rb
index dde592e..1c72d2d 100644
--- a/services/api/app/controllers/arvados/v1/schema_controller.rb
+++ b/services/api/app/controllers/arvados/v1/schema_controller.rb
@@ -37,7 +37,7 @@ class Arvados::V1::SchemaController < ApplicationController
         generatedAt: Time.now.iso8601,
         title: "Arvados API",
         description: "The API to interact with Arvados.",
-        documentationLink: "https://redmine.clinicalfuture.com/projects/arvados/",
+        documentationLink: "http://doc.arvados.org/api/index.html",
         protocol: "rest",
         baseUrl: root_url + "/arvados/v1/",
         basePath: "/arvados/v1/",
diff --git a/services/api/app/models/commit.rb b/services/api/app/models/commit.rb
index d7d0571..5e29c76 100644
--- a/services/api/app/models/commit.rb
+++ b/services/api/app/models/commit.rb
@@ -10,27 +10,114 @@ class Commit < ActiveRecord::Base
   # Examples: "1234567", "master", "apps:1234567", "apps:master",
   # "apps:HEAD"
 
-  def self.find_by_commit_ish(commit_ish)
-    want_repo = nil
-    if commit_ish.index(':')
-      want_repo, commit_ish = commit_ish.split(':',2)
+  # def self.find_by_commit_ish(commit_ish)
+  #   if only_valid_chars.match(commit_ish)       
+  #     logger.warn "find_by_commit_ish called with string containing invalid characters: '#{commit_ish}'"
+  #     return nil
+  #   end
+
+  #   want_repo = nil
+  #   if commit_ish.index(':')
+  #     want_repo, commit_ish = commit_ish.split(':',2)
+  #   end
+  #   repositories.each do |repo_name, repo|
+  #     next if want_repo and want_repo != repo_name
+  #     ENV['GIT_DIR'] = repo[:git_dir]
+  #     # we're passing user input to a command line, this is a potential a security hole but I am reasonably confident that shellescape sanitizes the input adequately
+  #     IO.foreach("|git rev-list --max-count=1 --format=oneline 'origin/'#{commit_ish.shellescape} 2>/dev/null || git rev-list --max-count=1 --format=oneline ''#{commit_ish.shellescape}") do |line|
+  #       sha1, message = line.strip.split " ", 2
+  #       next if sha1.length != 40
+  #       begin
+  #         Commit.find_or_create_by_repository_name_and_sha1_and_message(repo_name, sha1, message[0..254])
+  #       rescue
+  #         logger.warn "find_or_create failed: repo_name #{repo_name} sha1 #{sha1} message #{message[0..254]}"
+  #         # Ignore cache failure. Commit is real. We should proceed.
+  #       end
+  #       return sha1
+  #     end
+  #   end
+  #   nil
+  # end
+
+  def self.find_commit_range(current_user, repository, minimum, maximum)
+    only_valid_chars = /[^A-Za-z0-9_-]/
+    if only_valid_chars.match(minimum) || only_valid_chars.match(maximum) 
+      logger.warn "find_commit_range called with string containing invalid characters: '#{minimum}', '#{maximum}'"
+      return nil
     end
-    repositories.each do |repo_name, repo|
-      next if want_repo and want_repo != repo_name
-      ENV['GIT_DIR'] = repo[:git_dir]
-      IO.foreach("|git rev-list --max-count=1 --format=oneline 'origin/'#{commit_ish.shellescape} 2>/dev/null || git rev-list --max-count=1 --format=oneline ''#{commit_ish.shellescape}") do |line|
-        sha1, message = line.strip.split " ", 2
-        next if sha1.length != 40
-        begin
-          Commit.find_or_create_by_repository_name_and_sha1_and_message(repo_name, sha1, message[0..254])
-        rescue
-          logger.warn "find_or_create failed: repo_name #{repo_name} sha1 #{sha1} message #{message[0..254]}"
-          # Ignore cache failure. Commit is real. We should proceed.
+
+    if minimum and minimum.empty?
+        minimum = nil
+    end
+    
+    if !maximum
+      maximum = "HEAD"
+    end
+
+    # Get list of actual repository directories under management
+    on_disk_repos = repositories
+
+    # Get list of repository objects readable by user
+    readable = Repository.readable_by(current_user)
+
+    # filter repository objects on requested repository name
+    if repository
+      readable = readable.where(name: repository)
+    end
+
+    #puts "min #{minimum}"
+    #puts "max #{maximum}"
+    #puts "rep #{repository}"
+
+    commits = []
+    readable.each do |r|
+      if on_disk_repos[r.name]
+        ENV['GIT_DIR'] = on_disk_repos[r.name][:git_dir]
+
+        #puts "dir #{on_disk_repos[r.name][:git_dir]}"
+
+        # We've filtered for invalid characters, so we can pass the contents of
+        # minimum and maximum safely on the command line
+
+        #puts "git rev-list --max-count=1 #{maximum}"
+
+        # Get the commit hash for the upper bound
+        max_hash = nil
+        IO.foreach("|git rev-list --max-count=1 #{maximum}") do |line|
+          max_hash = line.strip
+        end
+
+        # If not found, nothing else to do
+        next if !max_hash
+
+        if minimum          
+          # Get the commit hash for the lower bound
+          min_hash = nil
+          IO.foreach("|git rev-list --max-count=1 #{minimum}") do |line|
+            min_hash = line.strip
+          end
+
+          # If not found, nothing else to do
+          next if !min_hash
+          
+          # Now find all commits between them
+          #puts "git rev-list #{min_hash}..#{max_hash}"
+          IO.foreach("|git rev-list #{min_hash}..#{max_hash}") do |line|
+            commits.push(line.strip)
+          end
+
+          commits.push(min_hash)
+        else
+          commits.push(max_hash)
         end
-        return sha1
       end
     end
-    nil
+
+    if !commits or commits.empty?
+      nil
+    else
+      commits
+    end
   end
 
   # Import all commits from configured git directory into the commits
@@ -59,6 +146,10 @@ class Commit < ActiveRecord::Base
     end
   end
 
+  def self.refresh_repositories
+    @repositories = nil
+  end
+
   protected
 
   def self.repositories
diff --git a/services/api/app/models/job.rb b/services/api/app/models/job.rb
index 1f0ef75..21414e2 100644
--- a/services/api/app/models/job.rb
+++ b/services/api/app/models/job.rb
@@ -36,6 +36,7 @@ class Job < ArvadosModel
     t.add :dependencies
     t.add :log_stream_href
     t.add :log_buffer
+    t.add :nondeterministic
   end
 
   def assert_finished
@@ -56,6 +57,11 @@ class Job < ArvadosModel
       order('priority desc, created_at')
   end
 
+  def self.running
+    self.where('running = ?', true).
+      order('priority desc, created_at')
+  end
+
   protected
 
   def foreign_key_attributes
@@ -70,7 +76,7 @@ class Job < ArvadosModel
       return true
     end
     if new_record? or script_version_changed?
-      sha1 = Commit.find_by_commit_ish(self.script_version) rescue nil
+      sha1 = Commit.find_commit_range(current_user, nil, nil, self.script_version)[0] rescue nil
       if sha1
         self.script_version = sha1
       else
diff --git a/services/api/db/migrate/20140317135600_add_nondeterministic_column_to_job.rb b/services/api/db/migrate/20140317135600_add_nondeterministic_column_to_job.rb
new file mode 100644
index 0000000..574001b
--- /dev/null
+++ b/services/api/db/migrate/20140317135600_add_nondeterministic_column_to_job.rb
@@ -0,0 +1,9 @@
+class AddNondeterministicColumnToJob < ActiveRecord::Migration
+  def up
+    add_column :jobs, :nondeterministic, :boolean
+  end
+
+  def down
+    remove_column :jobs, :nondeterministic
+  end
+end
diff --git a/services/api/script/crunch-dispatch.rb b/services/api/script/crunch-dispatch.rb
index a54e8ac..c450458 100755
--- a/services/api/script/crunch-dispatch.rb
+++ b/services/api/script/crunch-dispatch.rb
@@ -330,7 +330,7 @@ class Dispatcher
             api_client_id: 0)
       pipe_auth.save
 
-      puts `export ARVADOS_API_TOKEN=#{pipe_auth.api_token} && arv-run-pipeline-instance --run-here --no-wait --instance #{p.uuid}`
+      puts `export ARVADOS_API_TOKEN=#{pipe_auth.api_token} && arv-run-pipeline-instance --run-here --no-wait --debug --debug-level=3 --instance #{p.uuid}`
     end
   end
 
diff --git a/services/api/test/fixtures/jobs.yml b/services/api/test/fixtures/jobs.yml
index 9780067..edc64bd 100644
--- a/services/api/test/fixtures/jobs.yml
+++ b/services/api/test/fixtures/jobs.yml
@@ -110,3 +110,24 @@ barbaz:
     running: 0
     done: 1
   runtime_constraints: {}
+
+previous_job_run:
+  uuid: zzzzz-8i9sb-cjs4pklxxjykqqq
+  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  script: hash
+  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
+  script_parameters:
+    input: fa7aeb5140e2848d39b416daeef4ffc5+45
+    an_integer: "1"
+  success: true
+
+nondeterminisic_job_run:
+  uuid: zzzzz-8i9sb-cjs4pklxxjykyyy
+  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  script: hash2
+  script_version: 4fe459abe02d9b365932b8f5dc419439ab4e2577
+  script_parameters:
+    input: fa7aeb5140e2848d39b416daeef4ffc5+45
+    an_integer: "1"
+  success: true
+  nondeterministic: true
\ No newline at end of file
diff --git a/services/api/test/fixtures/repositories.yml b/services/api/test/fixtures/repositories.yml
new file mode 100644
index 0000000..eb91ded
--- /dev/null
+++ b/services/api/test/fixtures/repositories.yml
@@ -0,0 +1,4 @@
+foo:
+  uuid: zzzzz-2x53u-382brsig8rp3666
+  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  name: foo
\ No newline at end of file
diff --git a/services/api/test/functional/arvados/v1/commits_controller_test.rb b/services/api/test/functional/arvados/v1/commits_controller_test.rb
new file mode 100644
index 0000000..e884b34
--- /dev/null
+++ b/services/api/test/functional/arvados/v1/commits_controller_test.rb
@@ -0,0 +1,43 @@
+require 'test_helper'
+load 'test/functional/arvados/v1/git_setup.rb'
+
+class Arvados::V1::CommitsControllerTest < ActionController::TestCase
+  fixtures :repositories, :users
+  
+  include GitSetup
+  
+  test "test_find_commit_range" do
+    authorize_with :active
+
+  # single
+    a = Commit.find_commit_range(users(:active), nil, nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556')
+    assert_equal ['31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
+
+  #test "test_branch1" do
+    a = Commit.find_commit_range(users(:active), nil, nil, 'master')
+    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57'], a
+
+  #test "test_branch2" do
+    a = Commit.find_commit_range(users(:active), 'foo', nil, 'b1')
+    assert_equal ['1de84a854e2b440dc53bf42f8548afa4c17da332'], a
+
+  #test "test_branch3" do
+    a = Commit.find_commit_range(users(:active), 'foo', nil, 'HEAD')
+    assert_equal ['1de84a854e2b440dc53bf42f8548afa4c17da332'], a
+
+  #test "test_single_revision_repo" do
+    a = Commit.find_commit_range(users(:active), "foo", nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556')
+    assert_equal ['31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
+    a = Commit.find_commit_range(users(:active), "bar", nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556')
+    assert_equal nil, a
+
+  #test "test_multi_revision" do
+    a = Commit.find_commit_range(users(:active), nil, '31ce37fe365b3dc204300a3e4c396ad333ed0556', '077ba2ad3ea24a929091a9e6ce545c93199b8e57')
+    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57', '4fe459abe02d9b365932b8f5dc419439ab4e2577', '31ce37fe365b3dc204300a3e4c396ad333ed0556'], a
+
+  #test "test_tag" do
+    a = Commit.find_commit_range(users(:active), nil, 'tag1', 'master')
+    assert_equal ['077ba2ad3ea24a929091a9e6ce545c93199b8e57', '4fe459abe02d9b365932b8f5dc419439ab4e2577'], a
+  end
+
+end
diff --git a/services/api/test/functional/arvados/v1/git_setup.rb b/services/api/test/functional/arvados/v1/git_setup.rb
new file mode 100644
index 0000000..242542a
--- /dev/null
+++ b/services/api/test/functional/arvados/v1/git_setup.rb
@@ -0,0 +1,17 @@
+require 'fileutils'
+require 'tmpdir'
+
+module GitSetup
+  def setup
+    @tmpdir = Dir.mktmpdir()
+    #puts "setup #{@tmpdir}"
+    `cp test/test.git.tar #{@tmpdir} && cd #{@tmpdir} && tar xf test.git.tar`
+    Rails.configuration.git_repositories_dir = "#{@tmpdir}/test"
+    Commit.refresh_repositories
+  end
+
+  def teardown
+    #puts "teardown #{@tmpdir}"
+    FileUtils.remove_entry @tmpdir, true
+  end
+end
diff --git a/services/api/test/functional/arvados/v1/job_reuse_controller_test.rb b/services/api/test/functional/arvados/v1/job_reuse_controller_test.rb
new file mode 100644
index 0000000..f259144
--- /dev/null
+++ b/services/api/test/functional/arvados/v1/job_reuse_controller_test.rb
@@ -0,0 +1,119 @@
+require 'test_helper'
+load 'test/functional/arvados/v1/git_setup.rb'
+
+class Arvados::V1::JobReuseControllerTest < ActionController::TestCase
+  fixtures :repositories, :users, :jobs
+
+  include GitSetup
+
+  test "test_reuse_job" do
+    @controller = Arvados::V1::JobsController.new
+    authorize_with :active
+    post :create, job: {
+      script: "hash",
+      script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
+      script_parameters: {
+        input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
+        an_integer: '1'
+      }
+    }
+    assert_response :success
+    assert_not_nil assigns(:object)
+    new_job = JSON.parse(@response.body)
+    assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
+    assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
+  end
+
+  test "test_reuse_job_range" do
+    @controller = Arvados::V1::JobsController.new
+    authorize_with :active
+    post :create, job: {
+      script: "hash",
+      minimum_script_version: "tag1",
+      script_version: "master",
+      script_parameters: {
+        input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
+        an_integer: '1'
+      }
+    }
+    assert_response :success
+    assert_not_nil assigns(:object)
+    new_job = JSON.parse(@response.body)
+    assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
+    assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
+  end
+
+  test "test_cannot_reuse_job_different_input" do
+    @controller = Arvados::V1::JobsController.new
+    authorize_with :active
+    post :create, job: {
+      script: "hash",
+      script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
+      script_parameters: {
+        input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
+        an_integer: '2'
+      }
+    }
+    assert_response :success
+    assert_not_nil assigns(:object)
+    new_job = JSON.parse(@response.body)
+    assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
+    assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
+  end
+
+  test "test_cannot_reuse_job_different_version" do
+    @controller = Arvados::V1::JobsController.new
+    authorize_with :active
+    post :create, job: {
+      script: "hash",
+      script_version: "master",
+      script_parameters: {
+        input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
+        an_integer: '2'
+      }
+    }
+    assert_response :success
+    assert_not_nil assigns(:object)
+    new_job = JSON.parse(@response.body)
+    assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
+    assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
+  end
+
+  test "test_cannot_reuse_job_submitted_nondeterministic" do
+    @controller = Arvados::V1::JobsController.new
+    authorize_with :active
+    post :create, job: {
+      script: "hash",
+      script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
+      script_parameters: {
+        input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
+        an_integer: '1'
+      },
+      nondeterministic: true
+    }
+    assert_response :success
+    assert_not_nil assigns(:object)
+    new_job = JSON.parse(@response.body)
+    assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
+    assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
+  end
+
+  test "test_cannot_reuse_job_past_nondeterministic" do
+    @controller = Arvados::V1::JobsController.new
+    authorize_with :active
+    post :create, job: {
+      script: "hash2",
+      script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
+      script_parameters: {
+        input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
+        an_integer: '1'
+      }
+    }
+    assert_response :success
+    assert_not_nil assigns(:object)
+    new_job = JSON.parse(@response.body)
+    assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykyyy', new_job['uuid']
+    assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
+  end
+
+end
diff --git a/services/api/test/functional/arvados/v1/jobs_controller_test.rb b/services/api/test/functional/arvados/v1/jobs_controller_test.rb
index f68cbc2..3b6b786 100644
--- a/services/api/test/functional/arvados/v1/jobs_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/jobs_controller_test.rb
@@ -1,4 +1,5 @@
 require 'test_helper'
+load 'test/functional/arvados/v1/git_setup.rb'
 
 class Arvados::V1::JobsControllerTest < ActionController::TestCase
 
@@ -226,4 +227,6 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase
     }
     assert_response 422
   end
+
+
 end
diff --git a/services/api/test/test.git.tar b/services/api/test/test.git.tar
new file mode 100644
index 0000000..fdd7db6
Binary files /dev/null and b/services/api/test/test.git.tar differ

commit 8b7a06f6d4f3f40fc0b2a2d5debf4b4553cc4ba0
Merge: fe4b373 ed8493b
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Mar 17 14:14:20 2014 -0400

    Merge branch '2278-crunch-dispatcher-monitor-processes' into 2051-nondeterministic-jobs


commit fe4b3736c374e703d53ac3c444da7eb49a54a6d6
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Mar 17 14:12:11 2014 -0400

    Added "nondeterministic" column to Jobs table via migration.
    Added check for "nondeterministic" field to arv-run-pipeline-instance.

diff --git a/sdk/cli/bin/arv-run-pipeline-instance b/sdk/cli/bin/arv-run-pipeline-instance
index 91d7192..d9ebd49 100755
--- a/sdk/cli/bin/arv-run-pipeline-instance
+++ b/sdk/cli/bin/arv-run-pipeline-instance
@@ -472,7 +472,7 @@ class WhRunPipelineInstance
             end
 
             if candidate_job[:success]
-              unless @options[:no_reuse_finished]
+              unless @options[:no_reuse_finished] or c[:nondeterministic]
                 job = candidate_job
                 $stderr.puts "using #{job[:uuid]} (finished at #{job[:finished_at]}) for component #{cname}"
                 c[:job] = job
@@ -494,6 +494,7 @@ class WhRunPipelineInstance
               job = JobCache.create(:script => c[:script],
                                     :script_parameters => c[:script_parameters],
                                     :runtime_constraints => c[:runtime_constraints] || {},
+                                    :nondeterministic => c[:nondeterministic] || false,
                                     :script_version => c[:script_version] || 'master')
               if job
                 debuglog "component #{cname} new job #{job[:uuid]}"
diff --git a/services/api/db/schema.rb b/services/api/db/schema.rb
index df6ea9b..91d9106 100644
--- a/services/api/db/schema.rb
+++ b/services/api/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20140129184311) do
+ActiveRecord::Schema.define(:version => 20140317135600) do
 
   create_table "api_client_authorizations", :force => true do |t|
     t.string   "api_token",                                           :null => false
@@ -70,7 +70,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   create_table "collections", :force => true do |t|
     t.string   "locator"
     t.string   "owner_uuid"
-    t.datetime "created_at",                          :null => false
+    t.datetime "created_at"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
@@ -80,7 +80,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "redundancy_confirmed_by_client_uuid"
     t.datetime "redundancy_confirmed_at"
     t.integer  "redundancy_confirmed_as"
-    t.datetime "updated_at",                          :null => false
+    t.datetime "updated_at"
     t.string   "uuid"
     t.text     "manifest_text"
   end
@@ -104,8 +104,8 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "repository_name"
     t.string   "sha1"
     t.string   "message"
-    t.datetime "created_at",      :null => false
-    t.datetime "updated_at",      :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "commits", ["repository_name", "sha1"], :name => "index_commits_on_repository_name_and_sha1", :unique => true
@@ -133,8 +133,8 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
     t.text     "properties"
-    t.datetime "created_at",              :null => false
-    t.datetime "updated_at",              :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "humans", ["uuid"], :name => "index_humans_on_uuid", :unique => true
@@ -182,13 +182,14 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.boolean  "running"
     t.boolean  "success"
     t.string   "output"
-    t.datetime "created_at",               :null => false
-    t.datetime "updated_at",               :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
     t.string   "priority"
     t.string   "is_locked_by_uuid"
     t.string   "log"
     t.text     "tasks_summary"
     t.text     "runtime_constraints"
+    t.boolean  "nondeterministic"
   end
 
   add_index "jobs", ["created_at"], :name => "index_jobs_on_created_at"
@@ -232,7 +233,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   create_table "links", :force => true do |t|
     t.string   "uuid"
     t.string   "owner_uuid"
-    t.datetime "created_at",              :null => false
+    t.datetime "created_at"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
@@ -242,7 +243,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.string   "name"
     t.string   "head_uuid"
     t.text     "properties"
-    t.datetime "updated_at",              :null => false
+    t.datetime "updated_at"
     t.string   "head_kind"
   end
 
@@ -305,7 +306,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
   create_table "pipeline_instances", :force => true do |t|
     t.string   "uuid"
     t.string   "owner_uuid"
-    t.datetime "created_at",                                 :null => false
+    t.datetime "created_at"
     t.string   "modified_by_client_uuid"
     t.string   "modified_by_user_uuid"
     t.datetime "modified_at"
@@ -314,7 +315,7 @@ ActiveRecord::Schema.define(:version => 20140129184311) do
     t.text     "components"
     t.boolean  "success"
     t.boolean  "active",                  :default => false
-    t.datetime "updated_at",                                 :null => false
+    t.datetime "updated_at"
     t.text     "properties"
   end
 

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list