@Override
    public ProjectMap getProjectsByIdList(List<Integer> projIdList) {
      if (projIdList.isEmpty()) {
        return ProjectMap.empty();
      }

      List<StoredProject> projs =
          autoCommit(
              (handle, dao) ->
                  handle
                      .createQuery(
                          "select * from projects"
                              + " where site_id = :siteId"
                              + " and id "
                              + inLargeIdListExpression(projIdList))
                      .bind("siteId", siteId)
                      .map(new StoredProjectMapper(cfm))
                      .list());

      ImmutableMap.Builder<Integer, StoredProject> builder = ImmutableMap.builder();
      for (StoredProject proj : projs) {
        builder.put(proj.getId(), proj);
      }
      return new ProjectMap(builder.build());
    }
  @GET
  @Path("/api/sessions/{id}")
  public RestSession getSession(@PathParam("id") long id) throws ResourceNotFoundException {
    StoredSessionWithLastAttempt session = sm.getSessionStore(getSiteId()).getSessionById(id);

    StoredProject proj = rm.getProjectStore(getSiteId()).getProjectById(session.getProjectId());

    return RestModels.session(session, proj.getName());
  }
    @Override
    public <T> T deleteProject(int projId, ProjectObsoleteAction<T> func)
        throws ResourceNotFoundException {
      return transaction(
          (handle, dao) -> {
            StoredProject proj =
                requiredResource(
                    dao.getProjectByIdWithLockForDelete(siteId, projId), "project id=%d", projId);

            T res = func.call(new DatabaseProjectControlStore(handle, siteId), proj);

            dao.deleteProject(proj.getId());

            return res;
          },
          ResourceNotFoundException.class);
    }
  @GET
  @Path("/api/sessions/{id}/attempts")
  public RestSessionAttemptCollection getSessionAttempts(
      @PathParam("id") long id, @QueryParam("last_id") Long lastId)
      throws ResourceNotFoundException {

    ProjectStore rs = rm.getProjectStore(getSiteId());
    SessionStore ss = sm.getSessionStore(getSiteId());

    StoredSession session = ss.getSessionById(id);
    StoredProject project = rs.getProjectById(session.getProjectId());
    List<StoredSessionAttempt> attempts =
        ss.getAttemptsOfSession(id, 100, Optional.fromNullable(lastId));

    List<RestSessionAttempt> collection =
        attempts
            .stream()
            .map(attempt -> RestModels.attempt(session, attempt, project.getName()))
            .collect(Collectors.toList());

    return RestModels.attemptCollection(collection);
  }