aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wfar...@apache.org
Subject aurora git commit: Introduce DB entity objects and avoid ugly hacks around mybatis/thrift issues.
Date Mon, 13 Jul 2015 23:43:19 GMT
Repository: aurora
Updated Branches:
  refs/heads/master 703c9fb78 -> 1a01a5bf0


Introduce DB entity objects and avoid ugly hacks around mybatis/thrift issues.

Reviewed at https://reviews.apache.org/r/36407/


Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/1a01a5bf
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/1a01a5bf
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/1a01a5bf

Branch: refs/heads/master
Commit: 1a01a5bf0c362b0bd19c53acdf012772ef7fe123
Parents: 703c9fb
Author: Bill Farner <wfarner@apache.org>
Authored: Mon Jul 13 16:40:34 2015 -0700
Committer: Bill Farner <wfarner@apache.org>
Committed: Mon Jul 13 16:40:34 2015 -0700

----------------------------------------------------------------------
 config/findbugs/excludeFilter.xml               |  12 ++
 config/pmd/custom.xml                           |   3 +
 src/main/java/org/apache/aurora/GuavaUtils.java |  16 ++-
 .../scheduler/storage/db/CronJobMapper.java     |   6 +-
 .../scheduler/storage/db/DbCronJobStore.java    |  22 +---
 .../scheduler/storage/db/DbTaskStore.java       |  75 ++----------
 .../scheduler/storage/db/TaskConfigManager.java | 120 ++-----------------
 .../scheduler/storage/db/TaskConfigMapper.java  |  17 +--
 .../aurora/scheduler/storage/db/TaskMapper.java |  28 ++---
 .../storage/db/shims/ContainerShim.java         |  42 -------
 .../storage/db/shims/TaskConstraintShim.java    |  42 -------
 .../storage/db/views/AssignedPort.java          |  40 -------
 .../storage/db/views/CronJobWrapper.java        |  42 -------
 .../storage/db/views/DbAssignedTask.java        |  42 +++++++
 .../storage/db/views/DbConstraint.java          |  30 +++++
 .../scheduler/storage/db/views/DbContainer.java |  33 +++++
 .../storage/db/views/DbJobConfiguration.java    |  43 +++++++
 .../storage/db/views/DbScheduledTask.java       |  42 +++++++
 .../storage/db/views/DbTaskConfig.java          |  87 ++++++++++++++
 .../storage/db/views/DbTaskConstraint.java      |  45 +++++++
 .../scheduler/storage/db/views/Pairs.java       |  46 +++++++
 .../storage/db/views/ScheduledTaskWrapper.java  |  43 -------
 .../storage/db/views/TaskConfigRow.java         |  60 ----------
 .../scheduler/storage/db/views/TaskLink.java    |  40 -------
 .../scheduler/storage/db/CronJobMapper.xml      |  52 ++++----
 .../scheduler/storage/db/TaskConfigMapper.xml   |  42 +++----
 .../aurora/scheduler/storage/db/TaskMapper.xml  |  35 +++---
 .../storage/db/RowGarbageCollectorTest.java     |   8 +-
 28 files changed, 508 insertions(+), 605 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/config/findbugs/excludeFilter.xml
----------------------------------------------------------------------
diff --git a/config/findbugs/excludeFilter.xml b/config/findbugs/excludeFilter.xml
index e1c2503..7c65302 100644
--- a/config/findbugs/excludeFilter.xml
+++ b/config/findbugs/excludeFilter.xml
@@ -37,6 +37,18 @@ limitations under the License.
     </Or>
   </Match>
 
+  <!-- Warnings triggered for mybatis shim classes. -->
+  <Match>
+    <Package name="org.apache.aurora.scheduler.storage.db.views" />
+    <Or>
+      <!-- The shim classes trip these warnings since we have no code that explicitly sets fields,
+           but mybatis reflects and sets them for us.
+       -->
+      <Bug pattern="NP_UNWRITTEN_FIELD" />
+      <Bug pattern="UWF_UNWRITTEN_FIELD" />
+    </Or>
+  </Match>
+
   <!-- We don't make use of Java serialization and this can prevent, for example, declaring an
        HttpServlet as an anonymous inner class for testing. -->
   <Match>

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/config/pmd/custom.xml
----------------------------------------------------------------------
diff --git a/config/pmd/custom.xml b/config/pmd/custom.xml
index 8ad6228..c31cac9 100644
--- a/config/pmd/custom.xml
+++ b/config/pmd/custom.xml
@@ -51,6 +51,9 @@ limitations under the License.
     <!-- Unfortunately we have several large classes that trip this rule.
          TODO(wfarner): Break apart god classes. -->
     <exclude name="GodClass"/>
+
+    <!-- Classes that are only meant to be managed by mybatis with reflection trip this rule. -->
+    <exclude name="MissingStaticMethodInNonInstantiatableClass"/>
   </rule>
   <rule ref="rulesets/java/empty.xml">
     <!-- Configured below -->

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/GuavaUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/GuavaUtils.java b/src/main/java/org/apache/aurora/GuavaUtils.java
index 9903299..e3e90e3 100644
--- a/src/main/java/org/apache/aurora/GuavaUtils.java
+++ b/src/main/java/org/apache/aurora/GuavaUtils.java
@@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.stream.Collector;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.Service;
@@ -38,14 +39,25 @@ public final class GuavaUtils {
    */
   public static <T> Collector<T, ?, ImmutableSet<T>> toImmutableSet() {
     return Collector.of(
-        ImmutableSet::builder,
+        ImmutableSet.Builder<T>::new,
         ImmutableSet.Builder::add,
-        (ImmutableSet.Builder<T> l, ImmutableSet.Builder<T> r) -> l.addAll(r.build()),
+        (l, r) -> l.addAll(r.build()),
         ImmutableSet.Builder::build,
         UNORDERED);
   }
 
   /**
+   * Collector to create a Guava ImmutableList.
+   */
+  public static <T> Collector<T, ?, ImmutableList<T>> toImmutableList() {
+    return Collector.of(
+        ImmutableList.Builder<T>::new,
+        ImmutableList.Builder::add,
+        (l, r) -> l.addAll(r.build()),
+        ImmutableList.Builder::build);
+  }
+
+  /**
    * Interface for mocking. The Guava ServiceManager class is final.
    */
   public interface ServiceManagerIface {

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/CronJobMapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/CronJobMapper.java b/src/main/java/org/apache/aurora/scheduler/storage/db/CronJobMapper.java
index a5c6e99..b07928d 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/CronJobMapper.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/CronJobMapper.java
@@ -17,7 +17,7 @@ import java.util.List;
 
 import javax.annotation.Nullable;
 
-import org.apache.aurora.scheduler.storage.db.views.CronJobWrapper;
+import org.apache.aurora.scheduler.storage.db.views.DbJobConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.ibatis.annotations.Param;
@@ -33,8 +33,8 @@ interface CronJobMapper {
 
   void truncate();
 
-  List<CronJobWrapper> selectAll();
+  List<DbJobConfiguration> selectAll();
 
   @Nullable
-  CronJobWrapper select(@Param("job") IJobKey job);
+  DbJobConfiguration select(@Param("job") IJobKey job);
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/DbCronJobStore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/DbCronJobStore.java b/src/main/java/org/apache/aurora/scheduler/storage/db/DbCronJobStore.java
index 664255f..6a9c73e 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/DbCronJobStore.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/DbCronJobStore.java
@@ -15,14 +15,11 @@ package org.apache.aurora.scheduler.storage.db;
 
 import javax.inject.Inject;
 
-import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.collect.FluentIterable;
 
-import org.apache.aurora.gen.JobConfiguration;
 import org.apache.aurora.scheduler.storage.CronJobStore;
-import org.apache.aurora.scheduler.storage.db.views.CronJobWrapper;
-import org.apache.aurora.scheduler.storage.db.views.TaskConfigRow;
+import org.apache.aurora.scheduler.storage.db.views.DbJobConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobConfiguration;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 
@@ -65,22 +62,10 @@ class DbCronJobStore implements CronJobStore.Mutable {
     cronJobMapper.truncate();
   }
 
-  private final Function<CronJobWrapper, JobConfiguration> hydrateJob =
-      new Function<CronJobWrapper, JobConfiguration>() {
-        @Override
-        public JobConfiguration apply(CronJobWrapper row) {
-          JobConfiguration job = row.getJob();
-          job.setTaskConfig(taskConfigManager.getConfigHydrator().apply(
-              new TaskConfigRow(row.getTaskConfigRowId(), job.getTaskConfig())));
-          return job;
-        }
-      };
-
   @Override
   public Iterable<IJobConfiguration> fetchJobs() {
     return FluentIterable.from(cronJobMapper.selectAll())
-        .transform(hydrateJob)
-        .transform(IJobConfiguration.FROM_BUILDER)
+        .transform(DbJobConfiguration::toImmutable)
         .toList();
   }
 
@@ -88,7 +73,6 @@ class DbCronJobStore implements CronJobStore.Mutable {
   public Optional<IJobConfiguration> fetchJob(IJobKey jobKey) {
     requireNonNull(jobKey);
     return Optional.fromNullable(cronJobMapper.select(jobKey))
-        .transform(hydrateJob)
-        .transform(IJobConfiguration.FROM_BUILDER);
+        .transform(DbJobConfiguration::toImmutable);
   }
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/DbTaskStore.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/DbTaskStore.java b/src/main/java/org/apache/aurora/scheduler/storage/db/DbTaskStore.java
index 0f56411..a358408 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/DbTaskStore.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/DbTaskStore.java
@@ -13,8 +13,6 @@
  */
 package org.apache.aurora.scheduler.storage.db;
 
-import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -28,8 +26,6 @@ import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.inject.Inject;
@@ -39,14 +35,12 @@ import com.twitter.common.quantity.Time;
 import com.twitter.common.util.Clock;
 
 import org.apache.aurora.gen.ScheduledTask;
-import org.apache.aurora.gen.TaskConfig;
 import org.apache.aurora.scheduler.base.Query;
 import org.apache.aurora.scheduler.base.Query.Builder;
 import org.apache.aurora.scheduler.base.Tasks;
 import org.apache.aurora.scheduler.storage.TaskStore;
-import org.apache.aurora.scheduler.storage.db.views.AssignedPort;
-import org.apache.aurora.scheduler.storage.db.views.ScheduledTaskWrapper;
-import org.apache.aurora.scheduler.storage.db.views.TaskConfigRow;
+import org.apache.aurora.scheduler.storage.db.views.DbScheduledTask;
+import org.apache.aurora.scheduler.storage.db.views.Pairs;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
@@ -132,34 +126,23 @@ class DbTaskStore implements TaskStore.Mutable {
         });
 
     for (IScheduledTask task : tasks) {
-      long configId = configCache.getUnchecked(task.getAssignedTask().getTask());
+      InsertResult result = new InsertResult();
+      taskMapper.insertScheduledTask(
+          task,
+          configCache.getUnchecked(task.getAssignedTask().getTask()),
+          result);
 
-      ScheduledTaskWrapper wrappedTask = new ScheduledTaskWrapper(configId, task.newBuilder());
-      taskMapper.insertScheduledTask(wrappedTask);
       if (!task.getTaskEvents().isEmpty()) {
-        taskMapper.insertTaskEvents(wrappedTask.getId(), task.getTaskEvents());
+        taskMapper.insertTaskEvents(result.getId(), task.getTaskEvents());
       }
       if (!task.getAssignedTask().getAssignedPorts().isEmpty()) {
         taskMapper.insertPorts(
-            wrappedTask.getId(),
-            toAssignedPorts(task.getAssignedTask().getAssignedPorts()));
+            result.getId(),
+            Pairs.fromMap(task.getAssignedTask().getAssignedPorts()));
       }
     }
   }
 
-  private static List<AssignedPort> toAssignedPorts(Map<String, Integer> ports) {
-    // Mybatis does not seem to support inserting maps where the keys are not known in advance (it
-    // treats them as bags of properties, presumably like a cheap bean object).
-    // See https://github.com/mybatis/mybatis-3/pull/208, and seemingly-relevant code in
-    // https://github.com/mybatis/mybatis-3/blob/4cfc129938fd6b5cb20c4b741392e8b3fa41b529/src
-    // main/java/org/apache/ibatis/scripting/xmltags/ForEachSqlNode.java#L73-L77.
-    ImmutableList.Builder<AssignedPort> list = ImmutableList.builder();
-    for (Map.Entry<String, Integer> entry : ports.entrySet()) {
-      list.add(new AssignedPort(entry.getKey(), entry.getValue()));
-    }
-    return list.build();
-  }
-
   @Timed("db_storage_delete_all_tasks")
   @Override
   public void deleteAllTasks() {
@@ -216,7 +199,7 @@ class DbTaskStore implements TaskStore.Mutable {
   }
 
   private FluentIterable<IScheduledTask> matches(Query.Builder query) {
-    Iterable<ScheduledTaskWrapper> results;
+    Iterable<DbScheduledTask> results;
     Predicate<IScheduledTask> filter;
     if (query.get().getTaskIdsSize() == 1) {
       // Optimize queries that are scoped to a single task, as the dynamic SQL used for arbitrary
@@ -231,42 +214,8 @@ class DbTaskStore implements TaskStore.Mutable {
       filter = Predicates.alwaysTrue();
     }
 
-    final Function<TaskConfigRow, TaskConfig> configSaturator = configManager.getConfigHydrator();
     return FluentIterable.from(results)
-        .transform(populateAssignedPorts)
-        .transform(new Function<ScheduledTaskWrapper, ScheduledTaskWrapper>() {
-          @Override
-          public ScheduledTaskWrapper apply(ScheduledTaskWrapper task) {
-            configSaturator.apply(
-                new TaskConfigRow(
-                    task.getTaskConfigRowId(),
-                    task.getTask().getAssignedTask().getTask()));
-            return task;
-          }
-        })
-        .transform(UNWRAP)
-        .transform(IScheduledTask.FROM_BUILDER)
+        .transform(DbScheduledTask::toImmutable)
         .filter(filter);
   }
-
-  private final Function<ScheduledTaskWrapper, ScheduledTaskWrapper> populateAssignedPorts =
-      new Function<ScheduledTaskWrapper, ScheduledTaskWrapper>() {
-        @Override
-        public ScheduledTaskWrapper apply(ScheduledTaskWrapper task) {
-          ImmutableMap.Builder<String, Integer> ports = ImmutableMap.builder();
-          for (AssignedPort port : taskMapper.selectPorts(task.getId())) {
-            ports.put(port.getName(), port.getPort());
-          }
-          task.getTask().getAssignedTask().setAssignedPorts(ports.build());
-          return task;
-        }
-      };
-
-  private static final Function<ScheduledTaskWrapper, ScheduledTask> UNWRAP =
-      new Function<ScheduledTaskWrapper, ScheduledTask>() {
-        @Override
-        public ScheduledTask apply(ScheduledTaskWrapper task) {
-          return task.getTask();
-        }
-      };
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigManager.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigManager.java b/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigManager.java
index 2ec6b2d..30a258a 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigManager.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigManager.java
@@ -13,30 +13,16 @@
  */
 package org.apache.aurora.scheduler.storage.db;
 
-import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
 
 import javax.inject.Inject;
 
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-import org.apache.aurora.gen.Constraint;
-import org.apache.aurora.gen.Container;
-import org.apache.aurora.gen.TaskConfig;
-import org.apache.aurora.gen.TaskConstraint;
-import org.apache.aurora.scheduler.storage.db.views.TaskConfigRow;
-import org.apache.aurora.scheduler.storage.db.views.TaskLink;
+import com.google.common.collect.Maps;
+
+import org.apache.aurora.scheduler.storage.db.views.DbTaskConfig;
+import org.apache.aurora.scheduler.storage.db.views.Pairs;
 import org.apache.aurora.scheduler.storage.entities.IConstraint;
-import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
 import org.apache.aurora.scheduler.storage.entities.IValueConstraint;
 
@@ -52,73 +38,15 @@ class TaskConfigManager {
     this.jobKeyMapper = requireNonNull(jobKeyMapper);
   }
 
-  /**
-   * Replaces the shimmed {@link org.apache.thrift.TUnion} instances with the base thrift types.
-   * This is necessary because TUnion, as of thrift 0.9.1, restricts subclassing.  The copy
-   * constructor checks for equality on {@link Object#getClass()} rather than the subclass-friendly
-   * {@link Class#isInstance(Object).
-   */
-  private static final Function<TaskConfig, TaskConfig> REPLACE_UNION_TYPES =
-      new Function<TaskConfig, TaskConfig>() {
-        @Override
-        public TaskConfig apply(TaskConfig config) {
-          ImmutableSet.Builder<Constraint> constraints = ImmutableSet.builder();
-          for (Constraint constraint : config.getConstraints()) {
-            Constraint replacement = new Constraint()
-                .setName(constraint.getName());
-            replacement.setConstraint(
-                new TaskConstraint(
-                    constraint.getConstraint().getSetField(),
-                    constraint.getConstraint().getFieldValue()));
-            constraints.add(replacement);
-          }
-          config.setConstraints(constraints.build());
-
-          config.setContainer(
-              new Container(
-                  config.getContainer().getSetField(),
-                  config.getContainer().getFieldValue()));
-
-          return config;
-        }
-      };
-
-  /**
-   * Creates an instance of a caching function that will fill all relations in a task config.
-   *
-   * @return A function to populate relations in task configs.
-   */
-  Function<TaskConfigRow, TaskConfig> getConfigHydrator() {
-    // It appears that there is no way in mybatis to populate a field of type Map.  To work around
-    // this, we need to manually perform the query and associate the elements.
-    final LoadingCache<Long, Map<String, String>> taskLinkCache = CacheBuilder.newBuilder()
-        .build(new CacheLoader<Long, Map<String, String>>() {
-          @Override
-          public Map<String, String> load(Long configId) {
-            return getTaskLinks(configId);
-          }
-        });
-    Function<TaskConfigRow, TaskConfig> linkPopulator = new Function<TaskConfigRow, TaskConfig>() {
-      @Override
-      public TaskConfig apply(TaskConfigRow row) {
-        return row.getConfig().setTaskLinks(taskLinkCache.getUnchecked(row.getId()));
-      }
-    };
-
-    return Functions.compose(REPLACE_UNION_TYPES, linkPopulator);
-  }
-
   private Optional<Long> getConfigRow(ITaskConfig config) {
     // We could optimize this slightly by first comparing the un-hydrated row and breaking early.
 
-    Iterable<TaskConfigRow> configsInJob = getConfigs(config.getJob());
-
-    Map<ITaskConfig, TaskConfigRow> rowsToIds =
-        FluentIterable.from(configsInJob)
-            .uniqueIndex(
-                Functions.compose(ITaskConfig.FROM_BUILDER, getConfigHydrator()));
+    Map<ITaskConfig, DbTaskConfig> rowsByConfig =
+        Maps.uniqueIndex(
+            configMapper.selectConfigsByJob(config.getJob()),
+            DbTaskConfig::toImmutable);
 
-    return Optional.ofNullable(rowsToIds.get(config)).map(TaskConfigRow::getId);
+    return Optional.ofNullable(rowsByConfig.get(config)).map(DbTaskConfig::getRowId);
   }
 
   long insert(ITaskConfig config) {
@@ -167,9 +95,7 @@ class TaskConfigManager {
     if (!config.getTaskLinks().isEmpty()) {
       configMapper.insertTaskLinks(
           configInsert.getId(),
-          FluentIterable.from(config.getTaskLinks().entrySet())
-              .transform(TO_LINK)
-              .toList());
+          Pairs.fromMap(config.getTaskLinks()));
     }
 
     if (!config.getMetadata().isEmpty()) {
@@ -183,30 +109,4 @@ class TaskConfigManager {
 
     return configInsert.getId();
   }
-
-  Map<String, String> getTaskLinks(long configId) {
-    ImmutableMap.Builder<String, String> links = ImmutableMap.builder();
-    for (TaskLink link : configMapper.selectTaskLinks(configId)) {
-      links.put(link.getLabel(), link.getUrl());
-    }
-    return links.build();
-  }
-
-  List<TaskConfigRow> getConfigs(IJobKey job) {
-    requireNonNull(job);
-    return configMapper.selectConfigsByJob(job);
-  }
-
-  Set<Long> getTaskConfigIds(Set<String> scheduledTaskIds) {
-    requireNonNull(scheduledTaskIds);
-    return configMapper.selectConfigsByTaskId(scheduledTaskIds);
-  }
-
-  private static final Function<Map.Entry<String, String>, TaskLink> TO_LINK =
-      new Function<Map.Entry<String, String>, TaskLink>() {
-        @Override
-        public TaskLink apply(Map.Entry<String, String> entry) {
-          return new TaskLink(entry.getKey(), entry.getValue());
-        }
-      };
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.java b/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.java
index 19f67ad..48f1904 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.java
@@ -16,8 +16,9 @@ package org.apache.aurora.scheduler.storage.db;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.aurora.scheduler.storage.db.views.TaskConfigRow;
-import org.apache.aurora.scheduler.storage.db.views.TaskLink;
+import com.twitter.common.collections.Pair;
+
+import org.apache.aurora.scheduler.storage.db.views.DbTaskConfig;
 import org.apache.aurora.scheduler.storage.entities.IConstraint;
 import org.apache.aurora.scheduler.storage.entities.IDockerContainer;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
@@ -48,7 +49,7 @@ interface TaskConfigMapper extends GarbageCollectedTableMapper {
    * @param job Job to look up.
    * @return Task config row container.
    */
-  List<TaskConfigRow> selectConfigsByJob(IJobKey job);
+  List<DbTaskConfig> selectConfigsByJob(IJobKey job);
 
   /**
    * Looks up task config IDs by task IDs.
@@ -120,15 +121,7 @@ interface TaskConfigMapper extends GarbageCollectedTableMapper {
    */
   void insertTaskLinks(
       @Param("configId") long configId,
-      @Param("links") List<TaskLink> links);
-
-  /**
-   * Selects the task links associated with a {@link ITaskConfig}.
-   *
-   * @param configId Task config ID.
-   * @return Links associated with the task config.
-   */
-  List<TaskLink> selectTaskLinks(@Param("configId") long configId);
+      @Param("links") List<Pair<String, String>> links);
 
   /**
    * Inserts the container association within an {@link ITaskConfig}.

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/TaskMapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/TaskMapper.java b/src/main/java/org/apache/aurora/scheduler/storage/db/TaskMapper.java
index 7d499af..41ff6cc 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/TaskMapper.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/TaskMapper.java
@@ -18,10 +18,12 @@ import java.util.Set;
 
 import javax.annotation.Nullable;
 
+import com.twitter.common.collections.Pair;
+
 import org.apache.aurora.gen.JobKey;
 import org.apache.aurora.gen.TaskQuery;
-import org.apache.aurora.scheduler.storage.db.views.AssignedPort;
-import org.apache.aurora.scheduler.storage.db.views.ScheduledTaskWrapper;
+import org.apache.aurora.scheduler.storage.db.views.DbScheduledTask;
+import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskEvent;
 import org.apache.ibatis.annotations.Param;
 
@@ -35,7 +37,10 @@ interface TaskMapper {
    *
    * @param task Task to insert.
    */
-  void insertScheduledTask(ScheduledTaskWrapper task);
+  void insertScheduledTask(
+      @Param("task") IScheduledTask task,
+      @Param("configId") long configId,
+      @Param("result") InsertResult result);
 
   /**
    * Gets tasks based on a query.
@@ -43,7 +48,7 @@ interface TaskMapper {
    * @param query Query to use as a filter for tasks.
    * @return Tasks matching the query.
    */
-  List<ScheduledTaskWrapper> select(TaskQuery query);
+  List<DbScheduledTask> select(TaskQuery query);
 
   /**
    * Gets a task by ID.
@@ -52,7 +57,7 @@ interface TaskMapper {
    * @return Task with the specified ID.
    */
   @Nullable
-  ScheduledTaskWrapper selectById(@Param("taskId") String taskId);
+  DbScheduledTask selectById(@Param("taskId") String taskId);
 
   /**
    * Gets job keys of all stored tasks.
@@ -79,16 +84,9 @@ interface TaskMapper {
    * @param taskRowId Task row ID.
    * @param ports Assigned ports to insert.
    */
-  void insertPorts(@Param("taskRowId") long taskRowId, @Param("ports") List<AssignedPort> ports);
-
-  /**
-   * Selects the assigned ports association within an
-   * {@link org.apache.aurora.scheduler.storage.entities.IScheduledTask}.
-   *
-   * @param taskRowId Task row ID.
-   * @return Ports associated with the task.
-   */
-  List<AssignedPort> selectPorts(@Param("taskRowId") long taskRowId);
+  void insertPorts(
+      @Param("taskRowId") long taskRowId,
+      @Param("ports") List<Pair<String, Integer>> ports);
 
   /**
    * Deletes all task rows.

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/shims/ContainerShim.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/shims/ContainerShim.java b/src/main/java/org/apache/aurora/scheduler/storage/db/shims/ContainerShim.java
deleted file mode 100644
index 07a991d..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/shims/ContainerShim.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.shims;
-
-import org.apache.aurora.gen.Container;
-import org.apache.aurora.gen.DockerContainer;
-import org.apache.aurora.gen.MesosContainer;
-
-/**
- * An extension of {@link Container} that does not throw {@link NullPointerException} when
- * accessors are called on unset fields.
- */
-public class ContainerShim extends Container {
-  @Override
-  public DockerContainer getDocker() {
-    if (isSet(_Fields.DOCKER)) {
-      return super.getDocker();
-    } else {
-      return null;
-    }
-  }
-
-  @Override
-  public MesosContainer getMesos() {
-    if (isSet(_Fields.MESOS)) {
-      return super.getMesos();
-    } else {
-      return null;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/shims/TaskConstraintShim.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/shims/TaskConstraintShim.java b/src/main/java/org/apache/aurora/scheduler/storage/db/shims/TaskConstraintShim.java
deleted file mode 100644
index 4990af7..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/shims/TaskConstraintShim.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.shims;
-
-import org.apache.aurora.gen.LimitConstraint;
-import org.apache.aurora.gen.TaskConstraint;
-import org.apache.aurora.gen.ValueConstraint;
-
-/**
- * An extension of {@link TaskConstraint} that does not throw {@link NullPointerException} when
- * accessors are called on unset fields.
- */
-public class TaskConstraintShim extends TaskConstraint {
-  @Override
-  public ValueConstraint getValue() {
-    if (isSet(_Fields.VALUE)) {
-      return super.getValue();
-    } else {
-      return null;
-    }
-  }
-
-  @Override
-  public LimitConstraint getLimit() {
-    if (isSet(_Fields.LIMIT)) {
-      return super.getLimit();
-    } else {
-      return null;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/AssignedPort.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/AssignedPort.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/AssignedPort.java
deleted file mode 100644
index 0c6442c..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/views/AssignedPort.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.views;
-
-/**
- * Representation of a row in the task_ports table.
- */
-public class AssignedPort {
-  private final String name;
-  private final int port;
-
-  private AssignedPort() {
-    // Needed by mybatis.
-    this(null, -1);
-  }
-
-  public AssignedPort(String name, int port) {
-    this.name = name;
-    this.port = port;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public int getPort() {
-    return port;
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/CronJobWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/CronJobWrapper.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/CronJobWrapper.java
deleted file mode 100644
index 5202db5..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/views/CronJobWrapper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.views;
-
-import org.apache.aurora.gen.JobConfiguration;
-
-/**
- * Representation of a row in the cron_jobs table.
- */
-public class CronJobWrapper {
-  private final long taskConfigRowId;
-  private final JobConfiguration job;
-
-  private CronJobWrapper() {
-    // Needed by mybatis.
-    this(-1, null);
-  }
-
-  public CronJobWrapper(long taskConfigRowId, JobConfiguration job) {
-    this.taskConfigRowId = taskConfigRowId;
-    this.job = job;
-  }
-
-  public long getTaskConfigRowId() {
-    return taskConfigRowId;
-  }
-
-  public JobConfiguration getJob() {
-    return job;
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbAssignedTask.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbAssignedTask.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbAssignedTask.java
new file mode 100644
index 0000000..57858f2
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbAssignedTask.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import java.util.List;
+
+import com.twitter.common.collections.Pair;
+
+import org.apache.aurora.gen.AssignedTask;
+
+public final class DbAssignedTask {
+  private String taskId;
+  private String slaveId;
+  private String slaveHost;
+  private DbTaskConfig task;
+  private List<Pair<String, Integer>> assignedPorts;
+  private int instanceId;
+
+  private DbAssignedTask() {
+  }
+
+  AssignedTask toThrift() {
+    return new AssignedTask()
+        .setTaskId(taskId)
+        .setSlaveId(slaveId)
+        .setSlaveHost(slaveHost)
+        .setTask(task.toThrift())
+        .setAssignedPorts(Pairs.toMap(assignedPorts))
+        .setInstanceId(instanceId);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbConstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbConstraint.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbConstraint.java
new file mode 100644
index 0000000..9366757
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbConstraint.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import org.apache.aurora.gen.Constraint;
+
+public final class DbConstraint {
+  private String name;
+  private DbTaskConstraint constraint;
+
+  private DbConstraint() {
+  }
+
+  Constraint toThrift() {
+    return new Constraint()
+        .setName(name)
+        .setConstraint(constraint.toThrift());
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbContainer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbContainer.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbContainer.java
new file mode 100644
index 0000000..ae97638
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbContainer.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import org.apache.aurora.gen.Container;
+import org.apache.aurora.gen.DockerContainer;
+import org.apache.aurora.gen.MesosContainer;
+
+public final class DbContainer {
+  private DockerContainer docker;
+
+  private DbContainer() {
+  }
+
+  Container toThrift() {
+    if (docker == null) {
+      return Container.mesos(new MesosContainer());
+    } else {
+      return Container.docker(docker);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbJobConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbJobConfiguration.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbJobConfiguration.java
new file mode 100644
index 0000000..40a5013
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbJobConfiguration.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import org.apache.aurora.gen.CronCollisionPolicy;
+import org.apache.aurora.gen.Identity;
+import org.apache.aurora.gen.JobConfiguration;
+import org.apache.aurora.gen.JobKey;
+import org.apache.aurora.scheduler.storage.entities.IJobConfiguration;
+
+public final class DbJobConfiguration {
+  private JobKey key;
+  private Identity owner;
+  private String cronSchedule;
+  private CronCollisionPolicy cronCollisionPolicy;
+  private DbTaskConfig taskConfig;
+  private int instanceCount;
+
+  private DbJobConfiguration() {
+  }
+
+  public IJobConfiguration toImmutable() {
+    return IJobConfiguration.build(
+        new JobConfiguration()
+        .setKey(key)
+        .setOwner(owner)
+        .setCronSchedule(cronSchedule)
+        .setCronCollisionPolicy(cronCollisionPolicy)
+        .setTaskConfig(taskConfig.toThrift())
+        .setInstanceCount(instanceCount));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbScheduledTask.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbScheduledTask.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbScheduledTask.java
new file mode 100644
index 0000000..502a1fa
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbScheduledTask.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import java.util.List;
+
+import org.apache.aurora.gen.ScheduleStatus;
+import org.apache.aurora.gen.ScheduledTask;
+import org.apache.aurora.gen.TaskEvent;
+import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
+
+public final class DbScheduledTask {
+  private DbAssignedTask assignedTask;
+  private ScheduleStatus status;
+  private int failureCount;
+  private List<TaskEvent> taskEvents;
+  private String ancestorId;
+
+  private DbScheduledTask() {
+  }
+
+  public IScheduledTask toImmutable() {
+    return IScheduledTask.build(
+        new ScheduledTask()
+            .setAssignedTask(assignedTask.toThrift())
+            .setStatus(status)
+            .setFailureCount(failureCount)
+            .setTaskEvents(taskEvents)
+            .setAncestorId(ancestorId));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConfig.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConfig.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConfig.java
new file mode 100644
index 0000000..956c508
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConfig.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableSet;
+import com.twitter.common.collections.Pair;
+
+import org.apache.aurora.GuavaUtils;
+import org.apache.aurora.gen.Container;
+import org.apache.aurora.gen.ExecutorConfig;
+import org.apache.aurora.gen.Identity;
+import org.apache.aurora.gen.JobKey;
+import org.apache.aurora.gen.MesosContainer;
+import org.apache.aurora.gen.Metadata;
+import org.apache.aurora.gen.TaskConfig;
+import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
+
+public final class DbTaskConfig {
+  private long rowId;
+  private JobKey job;
+  private Identity owner;
+  private String environment;
+  private String jobName;
+  private boolean isService;
+  private double numCpus;
+  private long ramMb;
+  private long diskMb;
+  private int priority;
+  private int maxTaskFailures;
+  private boolean production;
+  private List<DbConstraint> constraints;
+  private List<String> requestedPorts;
+  private List<Pair<String, String>> taskLinks;
+  private String contactEmail;
+  private ExecutorConfig executorConfig;
+  private List<Metadata> metadata;
+  private DbContainer container;
+
+  private DbTaskConfig() {
+  }
+
+  public long getRowId() {
+    return rowId;
+  }
+
+  TaskConfig toThrift() {
+    return new TaskConfig()
+        .setJob(job)
+        .setOwner(owner)
+        .setEnvironment(environment)
+        .setJobName(jobName)
+        .setIsService(isService)
+        .setNumCpus(numCpus)
+        .setRamMb(ramMb)
+        .setDiskMb(diskMb)
+        .setPriority(priority)
+        .setMaxTaskFailures(maxTaskFailures)
+        .setProduction(production)
+        .setConstraints(constraints.stream()
+            .map(DbConstraint::toThrift)
+            .collect(GuavaUtils.toImmutableSet()))
+        .setRequestedPorts(ImmutableSet.copyOf(requestedPorts))
+        .setTaskLinks(Pairs.toMap(taskLinks))
+        .setContactEmail(contactEmail)
+        .setExecutorConfig(executorConfig)
+        .setMetadata(ImmutableSet.copyOf(metadata))
+        .setContainer(
+            container == null ? Container.mesos(new MesosContainer()) : container.toThrift());
+  }
+
+  public ITaskConfig toImmutable() {
+    return ITaskConfig.build(toThrift());
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConstraint.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConstraint.java
new file mode 100644
index 0000000..e3e1b7a
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/DbTaskConstraint.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import javax.annotation.Nullable;
+
+import org.apache.aurora.gen.LimitConstraint;
+import org.apache.aurora.gen.TaskConstraint;
+import org.apache.aurora.gen.ValueConstraint;
+
+public final class DbTaskConstraint {
+  private ValueConstraint value;
+  private LimitConstraint limit;
+
+  private DbTaskConstraint() {
+  }
+
+  private static boolean isSet(Object o) {
+    return o != null;
+  }
+
+  @Nullable
+  TaskConstraint toThrift() {
+    // Using the isSet shim to work around a well-intentioned PMD rule that prefers positive
+    // branching (would trip if we did value != null directly here.
+    if (isSet(value)) {
+      return TaskConstraint.value(value);
+    } else if (isSet(limit)) {
+      return TaskConstraint.limit(limit);
+    } else {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/Pairs.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/Pairs.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/Pairs.java
new file mode 100644
index 0000000..95a34e0
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/storage/db/views/Pairs.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.db.views;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+import com.twitter.common.collections.Pair;
+
+import org.apache.aurora.GuavaUtils;
+
+/**
+ * Utility class for translating collections of {@link Pair} to and from maps.
+ */
+public final class Pairs {
+
+  private Pairs() {
+    // Utility class.
+  }
+
+  public static <K, V> Map<K, V> toMap(Iterable<Pair<K, V>> pairs) {
+    ImmutableMap.Builder<K, V> map = ImmutableMap.builder();
+    for (Pair<K, V> pair : pairs) {
+      map.put(pair.getFirst(), pair.getSecond());
+    }
+    return map.build();
+  }
+
+  public static <K, V> List<Pair<K, V>> fromMap(Map<K, V> map) {
+    return map.entrySet().stream()
+        .map((e) -> Pair.of(e.getKey(), e.getValue()))
+        .collect(GuavaUtils.toImmutableList());
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/ScheduledTaskWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/ScheduledTaskWrapper.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/ScheduledTaskWrapper.java
deleted file mode 100644
index 3e0a2f7..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/views/ScheduledTaskWrapper.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.views;
-
-import org.apache.aurora.gen.ScheduledTask;
-import org.apache.aurora.scheduler.storage.db.InsertResult;
-
-/**
- * Representation of a row in the tasks table.
- */
-public class ScheduledTaskWrapper extends InsertResult {
-  private final long taskConfigRowId;
-  private final ScheduledTask task;
-
-  private ScheduledTaskWrapper() {
-    // Needed by mybatis.
-    this(-1, null);
-  }
-
-  public ScheduledTaskWrapper(long taskConfigRowId, ScheduledTask task) {
-    this.taskConfigRowId = taskConfigRowId;
-    this.task = task;
-  }
-
-  public long getTaskConfigRowId() {
-    return taskConfigRowId;
-  }
-
-  public ScheduledTask getTask() {
-    return task;
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskConfigRow.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskConfigRow.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskConfigRow.java
deleted file mode 100644
index 0160ae3..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskConfigRow.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.views;
-
-import java.util.Objects;
-
-import org.apache.aurora.gen.TaskConfig;
-
-/**
- * Representation of a row in the task_configs table.
- */
-public class TaskConfigRow {
-  private final long id;
-  private final TaskConfig config;
-
-  private TaskConfigRow() {
-    // Required for mybatis.
-    this(-1, null);
-  }
-
-  public TaskConfigRow(long id, TaskConfig config) {
-    this.id = id;
-    this.config = config;
-  }
-
-  public long getId() {
-    return id;
-  }
-
-  public TaskConfig getConfig() {
-    return config;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (!(obj instanceof TaskConfigRow)) {
-      return false;
-    }
-
-    TaskConfigRow other = (TaskConfigRow) obj;
-    return Objects.equals(id, other.id)
-        && Objects.equals(config, other.config);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(id, config);
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskLink.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskLink.java b/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskLink.java
deleted file mode 100644
index 52b09a9..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/db/views/TaskLink.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.db.views;
-
-/**
- * Representation of a row in the task_config_task_links table.
- */
-public class TaskLink {
-  private final String label;
-  private final String url;
-
-  private TaskLink() {
-    // Needed by mybatis.
-    this(null, null);
-  }
-
-  public TaskLink(String label, String url) {
-    this.label = label;
-    this.url = url;
-  }
-
-  public String getLabel() {
-    return label;
-  }
-
-  public String getUrl() {
-    return url;
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/resources/org/apache/aurora/scheduler/storage/db/CronJobMapper.xml
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/storage/db/CronJobMapper.xml b/src/main/resources/org/apache/aurora/scheduler/storage/db/CronJobMapper.xml
index 3826d9f..ee603f4 100644
--- a/src/main/resources/org/apache/aurora/scheduler/storage/db/CronJobMapper.xml
+++ b/src/main/resources/org/apache/aurora/scheduler/storage/db/CronJobMapper.xml
@@ -62,41 +62,37 @@
 
   <resultMap
       id="cronJobWrapperResultMap"
-      type="org.apache.aurora.scheduler.storage.db.views.CronJobWrapper">
+      type="org.apache.aurora.scheduler.storage.db.views.DbJobConfiguration">
 
     <id column="c_id" />
-    <result property="taskConfigRowId" column="c_task_config_row_id"/>
-    <association property="job" javaType="org.apache.aurora.gen.JobConfiguration" columnPrefix="c_">
-      <id column="id"/>
-      <result property="owner.role" column="j_role"/>
-      <result property="owner.user" column="creator_user"/>
-      <result
-          property="cronCollisionPolicy"
-          column="cron_collision_policy"
-          typeHandler="org.apache.aurora.scheduler.storage.db.typehandlers.CronCollisionPolicyTypeHandler"/>
-      <association
-          property="key"
-          resultMap="org.apache.aurora.scheduler.storage.db.JobKeyMapper.jobKeyMap"
-          columnPrefix="j_"/>
-      <association
-          property="taskConfig"
-          select="org.apache.aurora.scheduler.storage.db.TaskConfigMapper.selectConfig"
-          column="task_config_row_id"
-          foreignColumn="id"/>
-    </association>
+    <result property="owner.role" column="j_role"/>
+    <result property="owner.user" column="creator_user"/>
+    <result
+        property="cronCollisionPolicy"
+        column="cron_collision_policy"
+        typeHandler="org.apache.aurora.scheduler.storage.db.typehandlers.CronCollisionPolicyTypeHandler"/>
+    <association
+        property="key"
+        resultMap="org.apache.aurora.scheduler.storage.db.JobKeyMapper.jobKeyMap"
+        columnPrefix="j_"/>
+    <association
+        property="taskConfig"
+        select="org.apache.aurora.scheduler.storage.db.TaskConfigMapper.selectConfig"
+        column="task_config_row_id"
+        foreignColumn="id"/>
   </resultMap>
 
   <sql id="unscopedSelect">
     SELECT
       c.id AS c_id,
-      c.creator_user AS c_creator_user,
-      c.cron_schedule AS c_cron_schedule,
-      c.cron_collision_policy AS c_cron_collision_policy,
-      c.task_config_row_id AS c_task_config_row_id,
-      c.instance_count AS c_instance_count,
-      j.role AS c_j_role,
-      j.environment AS c_j_environment,
-      j.name AS c_j_name
+      c.creator_user AS creator_user,
+      c.cron_schedule AS cron_schedule,
+      c.cron_collision_policy AS cron_collision_policy,
+      c.task_config_row_id AS task_config_row_id,
+      c.instance_count AS instance_count,
+      j.role AS j_role,
+      j.environment AS j_environment,
+      j.name AS j_name
     FROM cron_jobs AS c
     INNER JOIN job_keys AS j ON j.id = c.job_key_id
   </sql>

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.xml
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.xml b/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.xml
index 3304728..bbd6713 100644
--- a/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.xml
+++ b/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskConfigMapper.xml
@@ -66,17 +66,13 @@
     </collection>
   </resultMap>
 
-  <!--
-    A subclass of TaskConstraint is used to work around trouble using TaskConstraint.  See docs in
-    TaskConstraintShim for details.
-  -->
-  <resultMap id="taskConstraintMap" type="org.apache.aurora.scheduler.storage.db.shims.TaskConstraintShim">
+  <resultMap id="taskConstraintMap" type="org.apache.aurora.scheduler.storage.db.views.DbTaskConstraint">
     <id column="id"/>
     <association property="value" resultMap="valueConstraintMap" columnPrefix="v_"/>
     <association property="limit" resultMap="limitConstraintMap" columnPrefix="l_"/>
   </resultMap>
 
-  <resultMap id="constraintMap" type="org.apache.aurora.gen.Constraint">
+  <resultMap id="constraintMap" type="org.apache.aurora.scheduler.storage.db.views.DbConstraint">
     <id column="id"/>
     <association property="constraint" resultMap="taskConstraintMap"/>
   </resultMap>
@@ -101,7 +97,7 @@
     <result column="image" property="image"/>
   </resultMap>
 
-  <resultMap id="containerMap" type="org.apache.aurora.scheduler.storage.db.shims.ContainerShim">
+  <resultMap id="containerMap" type="org.apache.aurora.scheduler.storage.db.views.DbContainer">
     <association property="docker" resultMap="dockerContainerMap"/>
   </resultMap>
 
@@ -109,8 +105,8 @@
     <id column="id" />
   </resultMap>
 
-  <resultMap id="taskConfigMap" type="org.apache.aurora.gen.TaskConfig">
-    <id column="id" />
+  <resultMap id="taskConfigMap" type="org.apache.aurora.scheduler.storage.db.views.DbTaskConfig">
+    <id column="id" property="rowId" />
     <result column="j_role" property="owner.role"/>
     <result column="j_environment" property="environment"/>
     <result column="j_name" property="jobName"/>
@@ -131,6 +127,11 @@
       <result column="port_name" />
     </collection>
     <collection property="metadata" resultMap="metadataMap" columnPrefix="m_"/>
+    <collection
+        property="taskLinks"
+        select="selectTaskLinks"
+        column="id"
+        foreignColumn="task_config_id"/>
   </resultMap>
 
   <sql id="unscopedConfigSelect">
@@ -168,15 +169,7 @@
     WHERE c.id = #{id}
   </select>
 
-  <resultMap
-      id="taskConfigRowMap"
-      type="org.apache.aurora.scheduler.storage.db.views.TaskConfigRow">
-
-    <id column="id" property="id" />
-    <association property="config" resultMap="taskConfigMap"/>
-  </resultMap>
-
-  <select id="selectConfigsByJob" resultMap="taskConfigRowMap">
+  <select id="selectConfigsByJob" resultMap="taskConfigMap">
     <include refid="unscopedConfigSelect"/>
     WHERE j.role = #{role}
       AND j.environment = #{environment}
@@ -257,14 +250,17 @@
     ) VALUES (
       <foreach item="link" collection="links" separator="),(">
         #{configId},
-        #{link.label},
-        #{link.url}
+        #{link.first},
+        #{link.second}
       </foreach>
     )
   </insert>
 
-  <resultMap id="taskLinkMap" type="org.apache.aurora.scheduler.storage.db.views.TaskLink">
-    <id column="id"/>
+  <resultMap id="taskLinkMap" type="com.twitter.common.collections.Pair">
+    <constructor>
+      <arg column="label"/>
+      <arg column="url"/>
+    </constructor>
   </resultMap>
 
   <select id="selectTaskLinks" resultMap="taskLinkMap">
@@ -273,7 +269,7 @@
       label,
       url
     FROM task_config_task_links
-    WHERE task_config_id = #{configId}
+    WHERE task_config_id = #{id}
   </select>
 
   <insert id="insertContainer">

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskMapper.xml
----------------------------------------------------------------------
diff --git a/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskMapper.xml b/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskMapper.xml
index 0b9e3d7..647744f 100644
--- a/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskMapper.xml
+++ b/src/main/resources/org/apache/aurora/scheduler/storage/db/TaskMapper.xml
@@ -18,7 +18,7 @@
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.apache.aurora.scheduler.storage.db.TaskMapper">
   <cache size="10000" readOnly="true" />
-  <insert id="insertScheduledTask" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+  <insert id="insertScheduledTask" useGeneratedKeys="true" keyColumn="id" keyProperty="result.id">
     INSERT INTO tasks (
       task_id,
       slave_row_id,
@@ -39,7 +39,7 @@
       #{task.status, typeHandler=org.apache.aurora.scheduler.storage.db.typehandlers.ScheduleStatusTypeHandler},
       #{task.failureCount},
       #{task.ancestorId},
-      #{taskConfigRowId}
+      #{configId}
     )
   </insert>
 
@@ -62,8 +62,9 @@
     ORDER BY e.timestamp_ms ASC
   </select>
 
-  <resultMap id="scheduledTaskMap" type="org.apache.aurora.gen.ScheduledTask">
+  <resultMap id="scheduledTaskMap" type="org.apache.aurora.scheduler.storage.db.views.DbScheduledTask">
     <id column="row_id"/>
+    <result column="c_id" property="taskConfigRowId"/>
     <result property="status"
             column="status"
             typeHandler="org.apache.aurora.scheduler.storage.db.typehandlers.ScheduleStatusTypeHandler" />
@@ -75,7 +76,12 @@
         property="assignedTask.task"
         select="org.apache.aurora.scheduler.storage.db.TaskConfigMapper.selectConfig"
         column="task_config_row_id"
-        foreignColumn="id"/>
+        foreignColumn="row_id"/>
+    <collection
+        property="assignedTask.assignedPorts"
+        select="selectPorts"
+        column="row_id"
+        foreignColumn="task_row_id"/>
     <collection
         property="taskEvents"
         select="selectTaskEvents"
@@ -83,12 +89,6 @@
         foreignColumn="task_row_id"/>
   </resultMap>
 
-  <resultMap id="taskWrapperMap" type="org.apache.aurora.scheduler.storage.db.views.ScheduledTaskWrapper">
-    <id column="row_id" property="id"/>
-    <result column="c_id" property="taskConfigRowId"/>
-    <association property="task" resultMap="scheduledTaskMap"/>
-  </resultMap>
-
   <sql id="unscopedSelect">
     SELECT
       t.id AS row_id,
@@ -109,13 +109,13 @@
     LEFT OUTER JOIN host_attributes AS h ON h.id = t.slave_row_id
   </sql>
 
-  <select id="selectById" resultMap="taskWrapperMap">
+  <select id="selectById" resultMap="scheduledTaskMap">
     <include refid="unscopedSelect"/>
     WHERE
       t.task_id = #{taskId}
   </select>
 
-  <select id="select" resultMap="taskWrapperMap">
+  <select id="select" resultMap="scheduledTaskMap">
     <include refid="unscopedSelect"/>
     <where>
       <if test="role != null">
@@ -206,14 +206,17 @@
     ) VALUES (
     <foreach item="port" collection="ports" separator="),(">
       #{taskRowId},
-      #{port.name},
-      #{port.port}
+      #{port.first},
+      #{port.second}
     </foreach>
     )
   </insert>
 
-  <resultMap id="portMap" type="org.apache.aurora.scheduler.storage.db.views.AssignedPort">
-    <id column="id"/>
+  <resultMap id="portMap" type="com.twitter.common.collections.Pair">
+    <constructor>
+      <arg column="name"/>
+      <arg column="port"/>
+    </constructor>
   </resultMap>
 
   <select id="selectPorts" resultMap="portMap">

http://git-wip-us.apache.org/repos/asf/aurora/blob/1a01a5bf/src/test/java/org/apache/aurora/scheduler/storage/db/RowGarbageCollectorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/db/RowGarbageCollectorTest.java b/src/test/java/org/apache/aurora/scheduler/storage/db/RowGarbageCollectorTest.java
index 00bf3b7..dd18a68 100644
--- a/src/test/java/org/apache/aurora/scheduler/storage/db/RowGarbageCollectorTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/storage/db/RowGarbageCollectorTest.java
@@ -25,7 +25,6 @@ import com.twitter.common.util.testing.FakeClock;
 import org.apache.aurora.gen.JobKey;
 import org.apache.aurora.scheduler.base.TaskTestUtil;
 import org.apache.aurora.scheduler.storage.Storage;
-import org.apache.aurora.scheduler.storage.db.views.ScheduledTaskWrapper;
 import org.apache.aurora.scheduler.storage.entities.IJobKey;
 import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
@@ -92,8 +91,7 @@ public class RowGarbageCollectorTest {
     taskConfigMapper.insert(CONFIG_A, new InsertResult());
     InsertResult a2Insert = new InsertResult();
     taskConfigMapper.insert(TASK_A2.getAssignedTask().getTask(), a2Insert);
-    taskMapper.insertScheduledTask(
-        new ScheduledTaskWrapper(a2Insert.getId(), TASK_A2.newBuilder()));
+    taskMapper.insertScheduledTask(TASK_A2, a2Insert.getId(), new InsertResult());
     jobKeyMapper.merge(JOB_B);
     taskConfigMapper.insert(CONFIG_B, new InsertResult());
     rowGc.runOneIteration();
@@ -103,8 +101,8 @@ public class RowGarbageCollectorTest {
     // populated, therefore full object equivalence cannot easily be used.
     assertEquals(
         TASK_A2.getAssignedTask().getTask().getRamMb(),
-        Iterables.getOnlyElement(taskConfigMapper.selectConfigsByJob(JOB_A))
-            .getConfig().getRamMb());
+        Iterables.getOnlyElement(taskConfigMapper.selectConfigsByJob(JOB_A)).toImmutable()
+            .getRamMb());
     assertEquals(ImmutableList.of(), taskConfigMapper.selectConfigsByJob(JOB_B));
   }
 }


Mime
View raw message