app/domain/image/ImageRepository.scala (90 lines of code) (raw):
package domain.image
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._
import repositories._
import repositories.Tables.{ImageRow, Image, GetResultImageRow}
import slick.driver.PostgresDriver.api._
import slick.jdbc.GetResult
import java.sql.Timestamp
import infra.datasource.LgtmoonDatabase
/** imageテーブルにアクセスする */
object ImageRepository extends ImageRepositoryTrait {
}
trait ImageRepositoryTrait {
val db = LgtmoonDatabase
// status定数
val CONVERTING: Short = 0
val AVAILABLE: Short = 1
/**
* status=0でレコードを作成する
*
* @return Future[Option[Long]] 画像のID
*/
def create(): Future[Option[Long]] = {
val timestamp = new Timestamp(System.currentTimeMillis())
val imageRow = ImageRow(0, "", timestamp, 0)
val action = for {
id <- Image returning Image.map(_.id) += imageRow
} yield Some(id)
db.run(action)
}
/**
* レコードのstatusを更新する
*
* @param id: Long 画像ID
* @param status: Short 更新後のstatusの値
* @return Future[Option[Int]]
*/
def updateStatus(id: Long, status: Short, bin: Array[Byte]): Future[Option[Int]] = {
val action = Image.filter(_.id === id)
.map(x => (x.status, x.bin))
.update((status, Some(bin)))
db.run(action).map {
// 正しい挙動(1件のレコードが更新される)
case num: Int if num == 1 => Some(num)
case _ => None
}.recover {
case e => None
}
}
/**
* 画像を最新20件取得する
*
* @param limit: Int 何件取得するか。デフォルト20
* @return Future[Option[Seq[ImageRow]]]
*/
def images(limit: Int = 20): Future[Option[Seq[ImageRow]]] = {
val action = Image.filter(_.status === AVAILABLE)
.sortBy(_.createdAt.desc)
.take(limit)
.result
db.run(action).map {
case images: Seq[ImageRow] => Some(images)
case _ => None
}.recover {
case e => None
}
}
def imageIds(limit: Int): Future[Option[Seq[Long]]] = {
val action = Image.filter(_.status === AVAILABLE)
.sortBy(_.createdAt.desc)
.map(p => p.id)
.take(limit)
.result
db.run(action).map {
case images: Seq[ImageRow] => Some(images)
case _ => None
}.recover {
case e => None
}
}
/**
* 画像を取得する
*
* @param id: Long
* @return Future[Option[ImageRow]]
*/
def image(id: Long): Future[Option[ImageRow]] = {
val action = Image.filter(_.id === id).result
db.run(action).map {
case images: Seq[ImageRow] if images.length > 0
=> Some(images(0))
case _ => None
}.recover {
case e => {
None
}
}
}
implicit val GetByteArr = GetResult(r => r.nextBytes)
/**
* random() はpostgres専用な気がする
*/
def randomIds(limit: Int = 20): Future[Option[Seq[Int]]] = {
val action = sql"""
SELECT id FROM image
WHERE status = 1
ORDER BY random()
LIMIT 20
""".as[Int]
db.run(action).map {
case ids: Seq[Int] => Some(ids)
case _ => None
}.recover {
case e => {
None
}
}
}
}