Integrate learn-classifier task into the app

This commit is contained in:
Eike Kettner 2020-09-01 00:21:19 +02:00
parent 0c97b4ef76
commit 68bb65572b
5 changed files with 53 additions and 6 deletions

View File

@ -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)

View File

@ -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))

View File

@ -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,

View File

@ -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(

View File

@ -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)
}
} }