mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-06 15:15:58 +00:00
Integrate learn-classifier task into the app
This commit is contained in:
parent
0c97b4ef76
commit
68bb65572b
@ -52,12 +52,12 @@ object BackendApp {
|
|||||||
queue <- JobQueue(store)
|
queue <- JobQueue(store)
|
||||||
loginImpl <- Login[F](store)
|
loginImpl <- Login[F](store)
|
||||||
signupImpl <- OSignup[F](store)
|
signupImpl <- OSignup[F](store)
|
||||||
collImpl <- OCollective[F](store)
|
joexImpl <- OJoex(JoexClient(httpClient), store)
|
||||||
|
collImpl <- OCollective[F](store, utStore, joexImpl)
|
||||||
sourceImpl <- OSource[F](store)
|
sourceImpl <- OSource[F](store)
|
||||||
tagImpl <- OTag[F](store)
|
tagImpl <- OTag[F](store)
|
||||||
equipImpl <- OEquipment[F](store)
|
equipImpl <- OEquipment[F](store)
|
||||||
orgImpl <- OOrganization(store)
|
orgImpl <- OOrganization(store)
|
||||||
joexImpl <- OJoex(JoexClient(httpClient), store)
|
|
||||||
uploadImpl <- OUpload(store, queue, cfg.files, joexImpl)
|
uploadImpl <- OUpload(store, queue, cfg.files, joexImpl)
|
||||||
nodeImpl <- ONode(store)
|
nodeImpl <- ONode(store)
|
||||||
jobImpl <- OJob(store, joexImpl)
|
jobImpl <- OJob(store, joexImpl)
|
||||||
|
@ -9,8 +9,12 @@ import docspell.backend.ops.OCollective._
|
|||||||
import docspell.common._
|
import docspell.common._
|
||||||
import docspell.store.queries.QCollective
|
import docspell.store.queries.QCollective
|
||||||
import docspell.store.records._
|
import docspell.store.records._
|
||||||
|
import docspell.store.usertask.UserTask
|
||||||
|
import docspell.store.usertask.UserTaskStore
|
||||||
import docspell.store.{AddResult, Store}
|
import docspell.store.{AddResult, Store}
|
||||||
|
|
||||||
|
import com.github.eikek.calev.CalEvent
|
||||||
|
|
||||||
trait OCollective[F[_]] {
|
trait OCollective[F[_]] {
|
||||||
|
|
||||||
def find(name: Ident): F[Option[RCollective]]
|
def find(name: Ident): F[Option[RCollective]]
|
||||||
@ -95,7 +99,11 @@ object OCollective {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def apply[F[_]: Effect](store: Store[F]): Resource[F, OCollective[F]] =
|
def apply[F[_]: Effect](
|
||||||
|
store: Store[F],
|
||||||
|
uts: UserTaskStore[F],
|
||||||
|
joex: OJoex[F]
|
||||||
|
): Resource[F, OCollective[F]] =
|
||||||
Resource.pure[F, OCollective[F]](new OCollective[F] {
|
Resource.pure[F, OCollective[F]](new OCollective[F] {
|
||||||
def find(name: Ident): F[Option[RCollective]] =
|
def find(name: Ident): F[Option[RCollective]] =
|
||||||
store.transact(RCollective.findById(name))
|
store.transact(RCollective.findById(name))
|
||||||
@ -105,6 +113,23 @@ object OCollective {
|
|||||||
.transact(RCollective.updateSettings(collective, sett))
|
.transact(RCollective.updateSettings(collective, sett))
|
||||||
.attempt
|
.attempt
|
||||||
.map(AddResult.fromUpdate)
|
.map(AddResult.fromUpdate)
|
||||||
|
.flatMap(res => updateLearnClassifierTask(collective, sett) *> res.pure[F])
|
||||||
|
|
||||||
|
def updateLearnClassifierTask(coll: Ident, sett: Settings) =
|
||||||
|
for {
|
||||||
|
id <- Ident.randomId[F]
|
||||||
|
on = sett.classifier.map(_.enabled).getOrElse(false)
|
||||||
|
timer = sett.classifier.map(_.schedule).getOrElse(CalEvent.unsafe(""))
|
||||||
|
ut = UserTask(
|
||||||
|
id,
|
||||||
|
LearnClassifierArgs.taskName,
|
||||||
|
on,
|
||||||
|
timer,
|
||||||
|
LearnClassifierArgs(coll)
|
||||||
|
)
|
||||||
|
_ <- uts.updateOneTask(AccountId(coll, LearnClassifierArgs.taskName), ut)
|
||||||
|
_ <- joex.notifyAllNodes
|
||||||
|
} yield ()
|
||||||
|
|
||||||
def findSettings(collective: Ident): F[Option[OCollective.Settings]] =
|
def findSettings(collective: Ident): F[Option[OCollective.Settings]] =
|
||||||
store.transact(RCollective.getSettings(collective))
|
store.transact(RCollective.getSettings(collective))
|
||||||
|
@ -14,6 +14,7 @@ import docspell.ftssolr.SolrFtsClient
|
|||||||
import docspell.joex.analysis.RegexNerFile
|
import docspell.joex.analysis.RegexNerFile
|
||||||
import docspell.joex.fts.{MigrationTask, ReIndexTask}
|
import docspell.joex.fts.{MigrationTask, ReIndexTask}
|
||||||
import docspell.joex.hk._
|
import docspell.joex.hk._
|
||||||
|
import docspell.joex.learn.LearnClassifierTask
|
||||||
import docspell.joex.notify._
|
import docspell.joex.notify._
|
||||||
import docspell.joex.pdfconv.ConvertAllPdfTask
|
import docspell.joex.pdfconv.ConvertAllPdfTask
|
||||||
import docspell.joex.pdfconv.PdfConvTask
|
import docspell.joex.pdfconv.PdfConvTask
|
||||||
@ -159,6 +160,13 @@ object JoexAppImpl {
|
|||||||
ConvertAllPdfTask.onCancel[F]
|
ConvertAllPdfTask.onCancel[F]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.withTask(
|
||||||
|
JobTask.json(
|
||||||
|
LearnClassifierArgs.taskName,
|
||||||
|
LearnClassifierTask[F](cfg.textAnalysis, blocker, analyser),
|
||||||
|
LearnClassifierTask.onCancel[F]
|
||||||
|
)
|
||||||
|
)
|
||||||
.resource
|
.resource
|
||||||
psch <- PeriodicScheduler.create(
|
psch <- PeriodicScheduler.create(
|
||||||
cfg.periodicScheduler,
|
cfg.periodicScheduler,
|
||||||
|
@ -12,11 +12,15 @@ import docspell.backend.ops.OCollective
|
|||||||
import docspell.common._
|
import docspell.common._
|
||||||
import docspell.joex.Config
|
import docspell.joex.Config
|
||||||
import docspell.joex.scheduler._
|
import docspell.joex.scheduler._
|
||||||
|
import docspell.store.records.RClassifierSetting
|
||||||
|
|
||||||
object LearnClassifierTask {
|
object LearnClassifierTask {
|
||||||
|
|
||||||
type Args = LearnClassifierArgs
|
type Args = LearnClassifierArgs
|
||||||
|
|
||||||
|
def onCancel[F[_]: Sync]: Task[F, Args, Unit] =
|
||||||
|
Task.log(_.warn("Cancelling learn-classifier task"))
|
||||||
|
|
||||||
def apply[F[_]: Sync: ContextShift](
|
def apply[F[_]: Sync: ContextShift](
|
||||||
cfg: Config.TextAnalysis,
|
cfg: Config.TextAnalysis,
|
||||||
blocker: Blocker,
|
blocker: Blocker,
|
||||||
@ -24,7 +28,7 @@ object LearnClassifierTask {
|
|||||||
): Task[F, Args, Unit] =
|
): Task[F, Args, Unit] =
|
||||||
Task { ctx =>
|
Task { ctx =>
|
||||||
(for {
|
(for {
|
||||||
sett <- findActiveSettings[F](ctx.args.collective, cfg)
|
sett <- findActiveSettings[F](ctx, cfg)
|
||||||
data = selectItems(
|
data = selectItems(
|
||||||
ctx,
|
ctx,
|
||||||
math.min(cfg.classification.itemCount, sett.itemCount),
|
math.min(cfg.classification.itemCount, sett.itemCount),
|
||||||
@ -52,10 +56,16 @@ object LearnClassifierTask {
|
|||||||
???
|
???
|
||||||
|
|
||||||
private def findActiveSettings[F[_]: Sync](
|
private def findActiveSettings[F[_]: Sync](
|
||||||
coll: Ident,
|
ctx: Context[F, Args],
|
||||||
cfg: Config.TextAnalysis
|
cfg: Config.TextAnalysis
|
||||||
): OptionT[F, OCollective.Classifier] =
|
): OptionT[F, OCollective.Classifier] =
|
||||||
???
|
if (cfg.classification.enabled)
|
||||||
|
OptionT(ctx.store.transact(RClassifierSetting.findById(ctx.args.collective)))
|
||||||
|
.filter(_.enabled)
|
||||||
|
.filter(_.category.nonEmpty)
|
||||||
|
.map(OCollective.Classifier.fromRecord)
|
||||||
|
else
|
||||||
|
OptionT.none
|
||||||
|
|
||||||
private def logInactiveWarning[F[_]: Sync](logger: Logger[F]): F[Unit] =
|
private def logInactiveWarning[F[_]: Sync](logger: Logger[F]): F[Unit] =
|
||||||
logger.warn(
|
logger.warn(
|
||||||
|
@ -102,5 +102,9 @@ object RClassifierSetting {
|
|||||||
created
|
created
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
object Classifier {
|
||||||
|
def fromRecord(r: RClassifierSetting): Classifier =
|
||||||
|
Classifier(r.enabled, r.schedule, r.itemCount, r.category.some)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user