mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-21 18:08:25 +00:00
Add rest endpoints to re-create the index
This commit is contained in:
@ -84,8 +84,28 @@ docspell.server {
|
||||
}
|
||||
}
|
||||
|
||||
fulltext-search {
|
||||
# Configuration of the full-text search engine.
|
||||
full-text-search {
|
||||
# The full-text search feature can be disabled. It requires an
|
||||
# additional index server available which needs additional
|
||||
# memory and disk space. It can be enabled later any time.
|
||||
#
|
||||
# Currently the SOLR search platform is supported.
|
||||
enabled = true
|
||||
|
||||
# When re-creating the complete index via a REST call, this key
|
||||
# is required. If left empty (the default), recreating the index
|
||||
# is disabled.
|
||||
#
|
||||
# Example curl command:
|
||||
# curl -XPOST http://localhost:7880/api/v1/open/fts/reIndexAll/test123
|
||||
recreate-key = ""
|
||||
|
||||
# Configuration for the SOLR backend.
|
||||
solr = {
|
||||
url = "http://localhost:8983/solr/docspell_core"
|
||||
commit-within = 1000
|
||||
}
|
||||
}
|
||||
|
||||
# Configuration for the backend.
|
||||
@ -147,14 +167,5 @@ docspell.server {
|
||||
# By default all files are allowed.
|
||||
valid-mime-types = [ ]
|
||||
}
|
||||
|
||||
# Configuration of the full-text search engine.
|
||||
full-text-search {
|
||||
enabled = true
|
||||
solr = {
|
||||
url = "http://localhost:8983/solr/docspell_core"
|
||||
commit-within = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
package docspell.restserver
|
||||
|
||||
import java.net.InetAddress
|
||||
import docspell.common._
|
||||
import docspell.backend.auth.Login
|
||||
import docspell.backend.{Config => BackendConfig}
|
||||
import docspell.common._
|
||||
import docspell.ftssolr.SolrConfig
|
||||
|
||||
case class Config(
|
||||
appName: String,
|
||||
@ -14,7 +15,7 @@ case class Config(
|
||||
auth: Login.Config,
|
||||
integrationEndpoint: Config.IntegrationEndpoint,
|
||||
maxItemPageSize: Int,
|
||||
fulltextSearch: Config.FulltextSearch
|
||||
fullTextSearch: Config.FullTextSearch
|
||||
)
|
||||
|
||||
object Config {
|
||||
@ -52,8 +53,8 @@ object Config {
|
||||
}
|
||||
}
|
||||
|
||||
case class FulltextSearch(enabled: Boolean)
|
||||
case class FullTextSearch(enabled: Boolean, recreateKey: Ident, solr: SolrConfig)
|
||||
|
||||
object FulltextSearch {}
|
||||
object FullTextSearch {}
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,11 @@ package docspell.restserver
|
||||
|
||||
import cats.implicits._
|
||||
import cats.effect._
|
||||
import org.http4s.client.Client
|
||||
import docspell.backend.BackendApp
|
||||
import docspell.common.NodeType
|
||||
import docspell.ftsclient.FtsClient
|
||||
import docspell.ftssolr.SolrFtsClient
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
@ -26,9 +29,15 @@ object RestAppImpl {
|
||||
blocker: Blocker
|
||||
): Resource[F, RestApp[F]] =
|
||||
for {
|
||||
backend <- BackendApp(cfg.backend, connectEC, httpClientEc, blocker)
|
||||
backend <- BackendApp(cfg.backend, connectEC, httpClientEc, blocker)(
|
||||
createFtsClient[F](cfg)
|
||||
)
|
||||
app = new RestAppImpl[F](cfg, backend)
|
||||
appR <- Resource.make(app.init.map(_ => app))(_.shutdown)
|
||||
} yield appR
|
||||
|
||||
private def createFtsClient[F[_]: ConcurrentEffect: ContextShift](
|
||||
cfg: Config
|
||||
)(client: Client[F]): Resource[F, FtsClient[F]] =
|
||||
SolrFtsClient(cfg.fullTextSearch.solr, client)
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ object RestServer {
|
||||
"email/sent" -> SentMailRoutes(restApp.backend, token),
|
||||
"usertask/notifydueitems" -> NotifyDueItemsRoutes(cfg, restApp.backend, token),
|
||||
"usertask/scanmailbox" -> ScanMailboxRoutes(restApp.backend, token),
|
||||
"calevent/check" -> CalEventCheckRoutes()
|
||||
"calevent/check" -> CalEventCheckRoutes(),
|
||||
"fts" -> FullTextIndexRoutes.secured(cfg, restApp.backend, token)
|
||||
)
|
||||
|
||||
def openRoutes[F[_]: Effect](cfg: Config, restApp: RestApp[F]): HttpRoutes[F] =
|
||||
@ -87,7 +88,8 @@ object RestServer {
|
||||
"signup" -> RegisterRoutes(restApp.backend, cfg),
|
||||
"upload" -> UploadRoutes.open(restApp.backend, cfg),
|
||||
"checkfile" -> CheckFileRoutes.open(restApp.backend),
|
||||
"integration" -> IntegrationEndpointRoutes.open(restApp.backend, cfg)
|
||||
"integration" -> IntegrationEndpointRoutes.open(restApp.backend, cfg),
|
||||
"fts" -> FullTextIndexRoutes.open(cfg, restApp.backend)
|
||||
)
|
||||
|
||||
def redirectTo[F[_]: Effect](path: String): HttpRoutes[F] = {
|
||||
|
@ -0,0 +1,60 @@
|
||||
package docspell.restserver.routes
|
||||
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
import cats.data.OptionT
|
||||
import org.http4s._
|
||||
//import org.http4s.circe.CirceEntityDecoder._
|
||||
import org.http4s.circe.CirceEntityEncoder._
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
|
||||
import docspell.common._
|
||||
import docspell.backend.BackendApp
|
||||
import docspell.backend.auth.AuthToken
|
||||
import docspell.restserver.Config
|
||||
import docspell.restserver.conv.Conversions
|
||||
|
||||
object FullTextIndexRoutes {
|
||||
|
||||
def secured[F[_]: Effect](
|
||||
cfg: Config,
|
||||
backend: BackendApp[F],
|
||||
user: AuthToken
|
||||
): HttpRoutes[F] =
|
||||
if (!cfg.fullTextSearch.enabled) notFound[F]
|
||||
else {
|
||||
val dsl = Http4sDsl[F]
|
||||
import dsl._
|
||||
|
||||
HttpRoutes.of {
|
||||
case POST -> Root / "reIndex" =>
|
||||
for {
|
||||
res <- backend.fulltext.reindexCollective(user.account).attempt
|
||||
resp <-
|
||||
Ok(Conversions.basicResult(res, "Full-text index will be re-created."))
|
||||
} yield resp
|
||||
}
|
||||
}
|
||||
|
||||
def open[F[_]: Effect](cfg: Config, backend: BackendApp[F]): HttpRoutes[F] =
|
||||
if (!cfg.fullTextSearch.enabled) notFound[F]
|
||||
else {
|
||||
val dsl = Http4sDsl[F]
|
||||
import dsl._
|
||||
|
||||
HttpRoutes.of {
|
||||
case POST -> Root / "reIndexAll" / Ident(id) =>
|
||||
for {
|
||||
res <-
|
||||
if (id.nonEmpty && id == cfg.fullTextSearch.recreateKey)
|
||||
backend.fulltext.reindexAll.attempt
|
||||
else Left(new Exception("The provided key is invalid.")).pure[F]
|
||||
resp <-
|
||||
Ok(Conversions.basicResult(res, "Full-text index will be re-created."))
|
||||
} yield resp
|
||||
}
|
||||
}
|
||||
|
||||
private def notFound[F[_]: Effect]: HttpRoutes[F] =
|
||||
HttpRoutes(_ => OptionT.pure(Response.notFound[F]))
|
||||
}
|
Reference in New Issue
Block a user