mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 10:29:34 +00:00
Store files in different binary stores
This commit is contained in:
parent
d3ef4b6166
commit
c812ea1009
@ -16,6 +16,7 @@ import docspell.common.Pools
|
||||
import docspell.joex.routes._
|
||||
import docspell.pubsub.naive.NaivePubSub
|
||||
import docspell.store.Store
|
||||
import docspell.store.file.FileRepositoryConfig
|
||||
import docspell.store.records.RInternalSetting
|
||||
|
||||
import org.http4s.HttpApp
|
||||
@ -41,7 +42,7 @@ object JoexServer {
|
||||
|
||||
store <- Store.create[F](
|
||||
cfg.jdbc,
|
||||
cfg.files.chunkSize,
|
||||
FileRepositoryConfig.Database(cfg.files.chunkSize),
|
||||
pools.connectEC
|
||||
)
|
||||
settings <- Resource.eval(store.transact(RInternalSetting.create))
|
||||
|
@ -18,6 +18,7 @@ import docspell.restserver.http4s.InternalHeader
|
||||
import docspell.restserver.ws.OutputEvent.KeepAlive
|
||||
import docspell.restserver.ws.OutputEvent
|
||||
import docspell.store.Store
|
||||
import docspell.store.file.FileRepositoryConfig
|
||||
import docspell.store.records.RInternalSetting
|
||||
import org.http4s._
|
||||
import org.http4s.blaze.client.BlazeClientBuilder
|
||||
@ -73,7 +74,7 @@ object RestServer {
|
||||
httpClient <- BlazeClientBuilder[F].resource
|
||||
store <- Store.create[F](
|
||||
cfg.backend.jdbc,
|
||||
cfg.backend.files.chunkSize,
|
||||
FileRepositoryConfig.Database(cfg.backend.files.chunkSize),
|
||||
pools.connectEC
|
||||
)
|
||||
setting <- Resource.eval(store.transact(RInternalSetting.create))
|
||||
|
@ -12,7 +12,7 @@ import cats.effect._
|
||||
import cats.~>
|
||||
import fs2._
|
||||
|
||||
import docspell.store.file.FileRepository
|
||||
import docspell.store.file.{FileRepository, FileRepositoryConfig}
|
||||
import docspell.store.impl.StoreImpl
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
@ -35,7 +35,7 @@ object Store {
|
||||
|
||||
def create[F[_]: Async](
|
||||
jdbc: JdbcConfig,
|
||||
chunkSize: Int,
|
||||
fileRepoConfig: FileRepositoryConfig,
|
||||
connectEC: ExecutionContext
|
||||
): Resource[F, Store[F]] = {
|
||||
val acquire = Sync[F].delay(new HikariDataSource())
|
||||
@ -50,7 +50,7 @@ object Store {
|
||||
ds.setDriverClassName(jdbc.driverClass)
|
||||
}
|
||||
xa = HikariTransactor(ds, connectEC)
|
||||
fr = FileRepository.genericJDBC(xa, ds, chunkSize)
|
||||
fr = FileRepository.apply(xa, ds, fileRepoConfig)
|
||||
st = new StoreImpl[F](fr, jdbc, xa)
|
||||
_ <- Resource.eval(st.migrate)
|
||||
} yield st
|
||||
|
@ -6,12 +6,19 @@
|
||||
|
||||
package docspell.store.file
|
||||
|
||||
import docspell.common
|
||||
import javax.sql.DataSource
|
||||
|
||||
import cats.effect._
|
||||
import fs2.io.file.Path
|
||||
|
||||
import docspell.common._
|
||||
import docspell.files.TikaMimetype
|
||||
import docspell.logging.Logger
|
||||
|
||||
import binny._
|
||||
import binny.fs.{FsBinaryStore, FsStoreConfig, PathMapping}
|
||||
import binny.jdbc.{GenericJdbcStore, JdbcStoreConfig}
|
||||
import binny.minio.{MinioBinaryStore, MinioConfig, S3KeyMapping}
|
||||
import scodec.bits.ByteVector
|
||||
|
||||
private[store] object BinnyUtils {
|
||||
@ -26,7 +33,7 @@ private[store] object BinnyUtils {
|
||||
coll <- Ident.fromString(cId)
|
||||
cat <- FileCategory.fromString(catId)
|
||||
file <- Ident.fromString(fId)
|
||||
} yield common.FileKey(coll, cat, file)
|
||||
} yield FileKey(coll, cat, file)
|
||||
case _ =>
|
||||
Left(s"Invalid format for file-key: $bid")
|
||||
}
|
||||
@ -57,4 +64,55 @@ private[store] object BinnyUtils {
|
||||
.asString
|
||||
)
|
||||
}
|
||||
|
||||
val pathMapping: PathMapping = {
|
||||
import binny.fs.PathMapping.syntax._
|
||||
|
||||
def toPath(base: Path, binaryId: BinaryId): Path = {
|
||||
val fkey = unsafeBinaryIdToFileKey(binaryId)
|
||||
base / fkey.collective.id / fkey.category.id.id / fkey.id.id / "file"
|
||||
}
|
||||
|
||||
def toId(file: Path): Option[BinaryId] =
|
||||
for {
|
||||
id <- file.parent
|
||||
cat <- id.parent
|
||||
fcat <- FileCategory.fromString(cat.asId.id).toOption
|
||||
coll <- cat.parent
|
||||
fkey = FileKey(Ident.unsafe(coll.asId.id), fcat, Ident.unsafe(id.asId.id))
|
||||
} yield fileKeyToBinaryId(fkey)
|
||||
|
||||
PathMapping(toPath)(toId)
|
||||
}
|
||||
|
||||
def binaryStore[F[_]: Async](
|
||||
cfg: FileRepositoryConfig,
|
||||
attrStore: AttributeStore[F],
|
||||
ds: DataSource,
|
||||
logger: Logger[F]
|
||||
): BinaryStore[F] =
|
||||
cfg match {
|
||||
case FileRepositoryConfig.Database(chunkSize) =>
|
||||
val jdbcConfig =
|
||||
JdbcStoreConfig("filechunk", chunkSize, BinnyUtils.TikaContentTypeDetect)
|
||||
GenericJdbcStore[F](ds, LoggerAdapter(logger), jdbcConfig, attrStore)
|
||||
|
||||
case FileRepositoryConfig.S3(endpoint, accessKey, secretKey, bucket, chunkSize) =>
|
||||
val keyMapping = S3KeyMapping.constant(bucket)
|
||||
val minioCfg = MinioConfig
|
||||
.default(endpoint, accessKey, secretKey, keyMapping)
|
||||
.copy(chunkSize = chunkSize, detect = BinnyUtils.TikaContentTypeDetect)
|
||||
|
||||
MinioBinaryStore[F](minioCfg, attrStore, LoggerAdapter(logger))
|
||||
|
||||
case FileRepositoryConfig.Directory(path, chunkSize) =>
|
||||
val fsConfig = FsStoreConfig(
|
||||
path,
|
||||
BinnyUtils.TikaContentTypeDetect,
|
||||
FsStoreConfig.OverwriteMode.Fail,
|
||||
BinnyUtils.pathMapping,
|
||||
chunkSize
|
||||
)
|
||||
FsBinaryStore[F](fsConfig, LoggerAdapter(logger), attrStore)
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ import fs2._
|
||||
|
||||
import docspell.common._
|
||||
|
||||
import binny.BinaryId
|
||||
import binny.jdbc.{GenericJdbcStore, JdbcStoreConfig}
|
||||
import binny.{BinaryId, BinaryStore}
|
||||
import doobie.Transactor
|
||||
|
||||
trait FileRepository[F[_]] {
|
||||
@ -33,16 +32,15 @@ trait FileRepository[F[_]] {
|
||||
|
||||
object FileRepository {
|
||||
|
||||
def genericJDBC[F[_]: Sync](
|
||||
def apply[F[_]: Async](
|
||||
xa: Transactor[F],
|
||||
ds: DataSource,
|
||||
chunkSize: Int
|
||||
cfg: FileRepositoryConfig
|
||||
): FileRepository[F] = {
|
||||
val attrStore = new AttributeStore[F](xa)
|
||||
val cfg = JdbcStoreConfig("filechunk", chunkSize, BinnyUtils.TikaContentTypeDetect)
|
||||
val log = docspell.logging.getLogger[F]
|
||||
val binStore = GenericJdbcStore[F](ds, BinnyUtils.LoggerAdapter(log), cfg, attrStore)
|
||||
val keyFun: FileKey => BinaryId = BinnyUtils.fileKeyToBinaryId
|
||||
val binStore: BinaryStore[F] = BinnyUtils.binaryStore(cfg, attrStore, ds, log)
|
||||
|
||||
new FileRepositoryImpl[F](binStore, attrStore, keyFun)
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2020 Eike K. & Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package docspell.store.file
|
||||
|
||||
import fs2.io.file.Path
|
||||
|
||||
sealed trait FileRepositoryConfig {}
|
||||
|
||||
object FileRepositoryConfig {
|
||||
|
||||
final case class Database(chunkSize: Int) extends FileRepositoryConfig
|
||||
|
||||
final case class S3(
|
||||
endpoint: String,
|
||||
accessKey: String,
|
||||
secretKey: String,
|
||||
bucketName: String,
|
||||
chunkSize: Int
|
||||
) extends FileRepositoryConfig
|
||||
|
||||
final case class Directory(path: Path, chunkSize: Int) extends FileRepositoryConfig
|
||||
|
||||
}
|
@ -11,7 +11,7 @@ import javax.sql.DataSource
|
||||
import cats.effect._
|
||||
|
||||
import docspell.common.LenientUri
|
||||
import docspell.store.file.FileRepository
|
||||
import docspell.store.file.{FileRepository, FileRepositoryConfig}
|
||||
import docspell.store.impl.StoreImpl
|
||||
import docspell.store.migrate.FlywayMigrate
|
||||
|
||||
@ -67,7 +67,8 @@ object StoreFixture {
|
||||
for {
|
||||
ds <- dataSource(jdbc)
|
||||
xa <- makeXA(ds)
|
||||
fr = FileRepository.genericJDBC[IO](xa, ds, 64 * 1024)
|
||||
cfg = FileRepositoryConfig.Database(64 * 1024)
|
||||
fr = FileRepository[IO](xa, ds, cfg)
|
||||
store = new StoreImpl[IO](fr, jdbc, xa)
|
||||
_ <- Resource.eval(store.migrate)
|
||||
} yield store
|
||||
|
@ -307,7 +307,8 @@ object Dependencies {
|
||||
val binny = Seq(
|
||||
"com.github.eikek" %% "binny-core" % BinnyVersion,
|
||||
"com.github.eikek" %% "binny-jdbc" % BinnyVersion,
|
||||
"com.github.eikek" %% "binny-minio" % BinnyVersion
|
||||
"com.github.eikek" %% "binny-minio" % BinnyVersion,
|
||||
"com.github.eikek" %% "binny-fs" % BinnyVersion
|
||||
)
|
||||
|
||||
// https://github.com/flyway/flyway
|
||||
|
Loading…
x
Reference in New Issue
Block a user