def updateCanonicalWithAlias()

in path-manager/app/services/PathStore.scala [132:181]


  def updateCanonicalWithAlias(newPath: String, id: Long): Either[String, Map[String, List[PathRecord]]] = {
    //This takes the canonical path and makes it an alias. And then adds a new canonical path for newPath.

    logger.debug(s"Updating $CANONICAL_PATH_TYPE path [$newPath] for [$id] and creating $ALIAS_PATH_TYPE to old path.")

    if (PathValidator.isInvalid(newPath)) {
      Left(s"invalid path [$newPath]")
    } else {
      val newPathRecord = Option(Dynamo.pathsTable.getItem("path", newPath)).map(PathRecord(_))
      val pathsForId = Dynamo.pathsTable.getIndex("id-index").query(new KeyAttribute("identifier", id)).asScala.map{ PathRecord(_) }
      val canonicalPathForId = pathsForId.find(_.`type`==CANONICAL_PATH_TYPE)

      if(newPathRecord.exists(_.identifier != id)) {
        logger.warn(s"Failed to update path [$newPath], already claimed by id [${newPathRecord.map{_.identifier}.get}], submitting id [$id]")
        Left("path already in use")
      } else {
        canonicalPathForId.map { existingRecord: PathRecord =>

          val existingPath = existingRecord.path
          val existingAliases = pathsForId.filter(_.`type` == ALIAS_PATH_TYPE)

          val updatedRecords = if (existingPath != newPath) {

            val newCanonicalRecord = existingRecord.copy(path = newPath, ceasedToBeCanonicalAt = None)

            logger.debug(s"Aliasing old path for item [$id]. old path[$existingPath] new path [$newPath]")
            val resultingAliasRecord = PathRecord(
              Dynamo.pathsTable.updateItem(new UpdateItemSpec()
                .withPrimaryKey("path", existingPath)
                .withAttributeUpdate(
                  new AttributeUpdate("type").put(ALIAS_PATH_TYPE),
                  new AttributeUpdate("ceasedToBeCanonicalAt").put(System.currentTimeMillis) // so we can keep the aliases order
                )
                .withReturnValues(ReturnValue.ALL_NEW) // this means we can call getItem below
              ).getItem
            )
            putPathItemAndAwaitIndexUpdate(newCanonicalRecord) //TODO this and the update above should be a transaction (in case the latter fails)
            List(newCanonicalRecord, resultingAliasRecord)
          } else {
            List(existingRecord)
          }
          logger.debug(s"updated $CANONICAL_PATH_TYPE path [$newPath] and added $ALIAS_PATH_TYPE to [$existingPath] id [$id] successfully")
          (updatedRecords ++ existingAliases).groupBy(_.`type`)
        }.toRight{
          logger.warn(s"Failed to update path [$newPath], no existing path found for id [$id]")
          s"unable to find $CANONICAL_PATH_TYPE record for $id"
        }
      }
    }
  }