mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 10:29:34 +00:00
Adopt modules to new collective table
This commit is contained in:
parent
77f22bb5ea
commit
26d7c91266
@ -26,7 +26,7 @@ trait EventContext {
|
||||
"account" -> Json.obj(
|
||||
"collective" -> event.account.collective.asJson,
|
||||
"user" -> event.account.login.asJson,
|
||||
"login" -> event.account.asJson
|
||||
"login" -> event.account.asAccountId.asJson
|
||||
),
|
||||
"content" -> content
|
||||
)
|
||||
|
@ -70,7 +70,7 @@ object BasicData {
|
||||
|
||||
def find(
|
||||
itemIds: NonEmptyList[Ident],
|
||||
account: AccountId,
|
||||
account: AccountInfo,
|
||||
now: Timestamp
|
||||
): ConnectionIO[Vector[Item]] = {
|
||||
import ItemQueryDsl._
|
||||
|
@ -46,7 +46,7 @@ object DeleteFieldValueCtx {
|
||||
for {
|
||||
now <- OptionT.liftF(Timestamp.current[ConnectionIO])
|
||||
items <- OptionT.liftF(Item.find(ev.items, ev.account, now))
|
||||
field <- OptionT(RCustomField.findById(ev.field, ev.account.collective))
|
||||
field <- OptionT(RCustomField.findById(ev.field, ev.account.collectiveId))
|
||||
msg = DeleteFieldValueCtx(
|
||||
ev,
|
||||
Data(
|
||||
@ -71,7 +71,7 @@ object DeleteFieldValueCtx {
|
||||
)
|
||||
|
||||
final case class Data(
|
||||
account: AccountId,
|
||||
account: AccountInfo,
|
||||
items: List[Item],
|
||||
field: Field,
|
||||
itemUrl: Option[String]
|
||||
|
@ -61,7 +61,7 @@ object ItemSelectionCtx {
|
||||
items.toList,
|
||||
ev.itemUrl,
|
||||
ev.more,
|
||||
ev.account.user.id
|
||||
ev.account.login.id
|
||||
)
|
||||
)
|
||||
} yield msg
|
||||
@ -73,12 +73,12 @@ object ItemSelectionCtx {
|
||||
items <- ev.items.traverse(Item.sample[F])
|
||||
} yield ItemSelectionCtx(
|
||||
ev,
|
||||
Data(ev.account, items.toList, ev.itemUrl, ev.more, ev.account.user.id)
|
||||
Data(ev.account, items.toList, ev.itemUrl, ev.more, ev.account.login.id)
|
||||
)
|
||||
)
|
||||
|
||||
final case class Data(
|
||||
account: AccountId,
|
||||
account: AccountInfo,
|
||||
items: List[Item],
|
||||
itemUrl: Option[String],
|
||||
more: Boolean,
|
||||
@ -89,7 +89,7 @@ object ItemSelectionCtx {
|
||||
io.circe.generic.semiauto.deriveEncoder
|
||||
|
||||
def create(
|
||||
account: AccountId,
|
||||
account: AccountInfo,
|
||||
items: Vector[ListItem],
|
||||
baseUrl: Option[LenientUri],
|
||||
more: Boolean,
|
||||
@ -100,7 +100,7 @@ object ItemSelectionCtx {
|
||||
items.map(Item(now)).toList,
|
||||
baseUrl.map(_.asString),
|
||||
more,
|
||||
account.user.id
|
||||
account.login.id
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ object SetFieldValueCtx {
|
||||
for {
|
||||
now <- OptionT.liftF(Timestamp.current[ConnectionIO])
|
||||
items <- OptionT.liftF(Item.find(ev.items, ev.account, now))
|
||||
field <- OptionT(RCustomField.findById(ev.field, ev.account.collective))
|
||||
field <- OptionT(RCustomField.findById(ev.field, ev.account.collectiveId))
|
||||
msg = SetFieldValueCtx(
|
||||
ev,
|
||||
Data(
|
||||
@ -70,7 +70,7 @@ object SetFieldValueCtx {
|
||||
)
|
||||
|
||||
final case class Data(
|
||||
account: AccountId,
|
||||
account: AccountInfo,
|
||||
items: List[Item],
|
||||
field: Field,
|
||||
value: String,
|
||||
|
@ -39,8 +39,8 @@ object TagsChangedCtx {
|
||||
def apply: Factory =
|
||||
EventContext.factory(ev =>
|
||||
for {
|
||||
tagsAdded <- RTag.findAllByNameOrId(ev.added, ev.account.collective)
|
||||
tagsRemov <- RTag.findAllByNameOrId(ev.removed, ev.account.collective)
|
||||
tagsAdded <- RTag.findAllByNameOrId(ev.added, ev.account.collectiveId)
|
||||
tagsRemov <- RTag.findAllByNameOrId(ev.removed, ev.account.collectiveId)
|
||||
now <- Timestamp.current[ConnectionIO]
|
||||
items <- Item.find(ev.items, ev.account, now)
|
||||
msg = TagsChangedCtx(
|
||||
@ -69,7 +69,7 @@ object TagsChangedCtx {
|
||||
)
|
||||
|
||||
final case class Data(
|
||||
account: AccountId,
|
||||
account: AccountInfo,
|
||||
items: List[Item],
|
||||
added: List[Tag],
|
||||
removed: List[Tag],
|
||||
|
@ -0,0 +1,19 @@
|
||||
package docspell.scheduler
|
||||
|
||||
import cats.Applicative
|
||||
import docspell.common.AccountInfo
|
||||
|
||||
/** Strategy to find the user that submitted the job. This is used to emit events about
|
||||
* starting/finishing jobs.
|
||||
*
|
||||
* If an account cannot be determined, no events can be send.
|
||||
*/
|
||||
trait FindJobOwner[F[_]] {
|
||||
def apply(job: Job[_]): F[Option[AccountInfo]]
|
||||
}
|
||||
|
||||
object FindJobOwner {
|
||||
|
||||
def none[F[_]: Applicative]: FindJobOwner[F] =
|
||||
(_: Job[_]) => Applicative[F].pure(None)
|
||||
}
|
@ -17,7 +17,8 @@ import docspell.store.Store
|
||||
case class JobStoreModuleBuilder[F[_]: Async](
|
||||
store: Store[F],
|
||||
pubsub: PubSubT[F],
|
||||
eventSink: EventSink[F]
|
||||
eventSink: EventSink[F],
|
||||
findJobOwner: FindJobOwner[F]
|
||||
) {
|
||||
def withPubsub(ps: PubSubT[F]): JobStoreModuleBuilder[F] =
|
||||
copy(pubsub = ps)
|
||||
@ -25,8 +26,11 @@ case class JobStoreModuleBuilder[F[_]: Async](
|
||||
def withEventSink(es: EventSink[F]): JobStoreModuleBuilder[F] =
|
||||
copy(eventSink = es)
|
||||
|
||||
def withFindJobOwner(f: FindJobOwner[F]): JobStoreModuleBuilder[F] =
|
||||
copy(findJobOwner = f)
|
||||
|
||||
def build: JobStoreModuleBuilder.Module[F] = {
|
||||
val jobStore = JobStorePublish(store, pubsub, eventSink)
|
||||
val jobStore = JobStorePublish(store, pubsub, eventSink, findJobOwner)
|
||||
val periodicTaskStore = PeriodicTaskStore(store, jobStore)
|
||||
val userTaskStore = UserTaskStoreImpl(store, periodicTaskStore)
|
||||
new JobStoreModuleBuilder.Module(
|
||||
@ -35,7 +39,8 @@ case class JobStoreModuleBuilder[F[_]: Async](
|
||||
jobStore,
|
||||
store,
|
||||
eventSink,
|
||||
pubsub
|
||||
pubsub,
|
||||
findJobOwner
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -43,7 +48,12 @@ case class JobStoreModuleBuilder[F[_]: Async](
|
||||
object JobStoreModuleBuilder {
|
||||
|
||||
def apply[F[_]: Async](store: Store[F]): JobStoreModuleBuilder[F] =
|
||||
JobStoreModuleBuilder(store, PubSubT.noop[F], EventSink.silent[F])
|
||||
JobStoreModuleBuilder(
|
||||
store,
|
||||
PubSubT.noop[F],
|
||||
EventSink.silent[F],
|
||||
FindJobOwner.none[F]
|
||||
)
|
||||
|
||||
final class Module[F[_]](
|
||||
val userTasks: UserTaskStore[F],
|
||||
@ -51,6 +61,7 @@ object JobStoreModuleBuilder {
|
||||
val jobs: JobStore[F],
|
||||
val store: Store[F],
|
||||
val eventSink: EventSink[F],
|
||||
val pubSubT: PubSubT[F]
|
||||
val pubSubT: PubSubT[F],
|
||||
val findJobOwner: FindJobOwner[F]
|
||||
) extends JobStoreModule[F] {}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@
|
||||
|
||||
package docspell.scheduler.impl
|
||||
|
||||
import cats.data.OptionT
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common.{Ident, JobState}
|
||||
import docspell.notification.api.{Event, EventSink}
|
||||
import docspell.pubsub.api.PubSubT
|
||||
@ -19,26 +19,31 @@ import docspell.store.Store
|
||||
final class JobStorePublish[F[_]: Sync](
|
||||
delegate: JobStore[F],
|
||||
pubsub: PubSubT[F],
|
||||
eventSink: EventSink[F]
|
||||
eventSink: EventSink[F],
|
||||
findJobOwner: FindJobOwner[F]
|
||||
) extends JobStore[F] {
|
||||
|
||||
private def msg(job: Job[String]): JobSubmitted =
|
||||
JobSubmitted(job.id, job.group, job.task, job.args)
|
||||
|
||||
private def event(job: Job[String]): Event.JobSubmitted =
|
||||
Event.JobSubmitted(
|
||||
job.id,
|
||||
job.group,
|
||||
job.task,
|
||||
job.args,
|
||||
JobState.waiting,
|
||||
job.subject,
|
||||
job.submitter
|
||||
)
|
||||
private def event(job: Job[String]): OptionT[F, Event.JobSubmitted] =
|
||||
OptionT(findJobOwner(job))
|
||||
.map(
|
||||
Event.JobSubmitted(
|
||||
_,
|
||||
job.id,
|
||||
job.group,
|
||||
job.task,
|
||||
job.args,
|
||||
JobState.waiting,
|
||||
job.subject,
|
||||
job.submitter
|
||||
)
|
||||
)
|
||||
|
||||
private def publish(job: Job[String]): F[Unit] =
|
||||
pubsub.publish1(JobSubmitted.topic, msg(job)).as(()) *>
|
||||
eventSink.offer(event(job))
|
||||
event(job).semiflatMap(eventSink.offer).value.void
|
||||
|
||||
private def notifyJoex: F[Unit] =
|
||||
pubsub.publish1IgnoreErrors(JobsNotify(), ()).void
|
||||
@ -82,7 +87,8 @@ object JobStorePublish {
|
||||
def apply[F[_]: Async](
|
||||
store: Store[F],
|
||||
pubSub: PubSubT[F],
|
||||
eventSink: EventSink[F]
|
||||
eventSink: EventSink[F],
|
||||
findJobOwner: FindJobOwner[F]
|
||||
): JobStore[F] =
|
||||
new JobStorePublish[F](JobStoreImpl(store), pubSub, eventSink)
|
||||
new JobStorePublish[F](JobStoreImpl(store), pubSub, eventSink, findJobOwner)
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ case class SchedulerBuilder[F[_]: Async](
|
||||
queue: JobQueue[F],
|
||||
logSink: LogSink[F],
|
||||
pubSub: PubSubT[F],
|
||||
eventSink: EventSink[F]
|
||||
eventSink: EventSink[F],
|
||||
findJobOwner: FindJobOwner[F]
|
||||
) {
|
||||
|
||||
def withConfig(cfg: SchedulerConfig): SchedulerBuilder[F] =
|
||||
@ -32,7 +33,7 @@ case class SchedulerBuilder[F[_]: Async](
|
||||
def withTaskRegistry(reg: JobTaskRegistry[F]): SchedulerBuilder[F] =
|
||||
copy(tasks = reg)
|
||||
|
||||
def withTask[A](task: JobTask[F]): SchedulerBuilder[F] =
|
||||
def withTask(task: JobTask[F]): SchedulerBuilder[F] =
|
||||
withTaskRegistry(tasks.withTask(task))
|
||||
|
||||
def withLogSink(sink: LogSink[F]): SchedulerBuilder[F] =
|
||||
@ -47,6 +48,9 @@ case class SchedulerBuilder[F[_]: Async](
|
||||
def withEventSink(sink: EventSink[F]): SchedulerBuilder[F] =
|
||||
copy(eventSink = sink)
|
||||
|
||||
def withFindJobOwner(f: FindJobOwner[F]): SchedulerBuilder[F] =
|
||||
copy(findJobOwner = f)
|
||||
|
||||
def serve: Resource[F, Scheduler[F]] =
|
||||
resource.evalMap(sch => Async[F].start(sch.start.compile.drain).map(_ => sch))
|
||||
|
||||
@ -60,6 +64,7 @@ case class SchedulerBuilder[F[_]: Async](
|
||||
queue,
|
||||
pubSub,
|
||||
eventSink,
|
||||
findJobOwner,
|
||||
tasks,
|
||||
store,
|
||||
logSink,
|
||||
@ -86,6 +91,7 @@ object SchedulerBuilder {
|
||||
JobQueue(store),
|
||||
LogSink.db[F](store),
|
||||
PubSubT.noop[F],
|
||||
EventSink.silent[F]
|
||||
EventSink.silent[F],
|
||||
FindJobOwner.none[F]
|
||||
)
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ final class SchedulerImpl[F[_]: Async](
|
||||
queue: JobQueue[F],
|
||||
pubSub: PubSubT[F],
|
||||
eventSink: EventSink[F],
|
||||
findJobOwner: FindJobOwner[F],
|
||||
tasks: JobTaskRegistry[F],
|
||||
store: Store[F],
|
||||
logSink: LogSink[F],
|
||||
@ -68,20 +69,19 @@ final class SchedulerImpl[F[_]: Async](
|
||||
def getRunning: F[Vector[Job[String]]] =
|
||||
state.get
|
||||
.flatMap(s => QJob.findAll(s.getRunning, store))
|
||||
.map(
|
||||
_.map(rj =>
|
||||
Job(
|
||||
rj.id,
|
||||
rj.task,
|
||||
rj.group,
|
||||
rj.args,
|
||||
rj.subject,
|
||||
rj.submitter,
|
||||
rj.priority,
|
||||
rj.tracker
|
||||
)
|
||||
)
|
||||
)
|
||||
.map(_.map(convertJob))
|
||||
|
||||
private def convertJob(rj: RJob): Job[String] =
|
||||
Job(
|
||||
rj.id,
|
||||
rj.task,
|
||||
rj.group,
|
||||
rj.args,
|
||||
rj.subject,
|
||||
rj.submitter,
|
||||
rj.priority,
|
||||
rj.tracker
|
||||
)
|
||||
|
||||
def requestCancel(jobId: Ident): F[Boolean] =
|
||||
logger.info(s"Scheduler requested to cancel job: ${jobId.id}") *>
|
||||
@ -235,22 +235,29 @@ final class SchedulerImpl[F[_]: Async](
|
||||
)
|
||||
)
|
||||
_ <- Sync[F].whenA(JobState.isDone(finishState))(
|
||||
eventSink.offer(
|
||||
Event.JobDone(
|
||||
job.id,
|
||||
job.group,
|
||||
job.task,
|
||||
job.args,
|
||||
job.state,
|
||||
job.subject,
|
||||
job.submitter,
|
||||
result.json.getOrElse(Json.Null),
|
||||
result.message
|
||||
)
|
||||
)
|
||||
makeJobDoneEvent(job, result)
|
||||
.semiflatMap(eventSink.offer)
|
||||
.value
|
||||
)
|
||||
} yield ()
|
||||
|
||||
private def makeJobDoneEvent(job: RJob, result: JobTaskResult) =
|
||||
for {
|
||||
acc <- OptionT(findJobOwner(convertJob(job)))
|
||||
ev = Event.JobDone(
|
||||
acc,
|
||||
job.id,
|
||||
job.group,
|
||||
job.task,
|
||||
job.args,
|
||||
job.state,
|
||||
job.subject,
|
||||
job.submitter,
|
||||
result.json.getOrElse(Json.Null),
|
||||
result.message
|
||||
)
|
||||
} yield ev
|
||||
|
||||
def onStart(job: RJob): F[Unit] =
|
||||
QJob.setRunning(
|
||||
job.id,
|
||||
|
Loading…
x
Reference in New Issue
Block a user