1 {-# OPTIONS_GHC -fno-warn-unused-top-binds #-}
3 Module : Gargantext.API.Ngrams
4 Description : Server API
5 Copyright : (c) CNRS, 2017-Present
6 License : AGPL + CECILL v3
7 Maintainer : team@gargantext.org
8 Stability : experimental
14 get ngrams filtered by NgramsType
19 {-# LANGUAGE ConstraintKinds #-}
20 {-# LANGUAGE ScopedTypeVariables #-}
21 {-# LANGUAGE TypeOperators #-}
22 {-# LANGUAGE TypeFamilies #-}
24 module Gargantext.API.Ngrams
31 --, rmListNgrams TODO fix before exporting
32 , apiNgramsTableCorpus
55 , NgramsRepoElement(..)
81 , listNgramsChangedSince
85 import Control.Concurrent
86 import Control.Lens ((.~), view, (^.), (^..), (+~), (%~), (.~), sumOf, at, _Just, Each(..), (%%~), mapped, ifolded, withIndex)
87 import Control.Monad.Reader
88 import Data.Aeson hiding ((.=))
89 import qualified Data.Aeson.Text as DAT
90 import Data.Either (Either(..))
92 import qualified Data.List as List
93 import Data.Map.Strict (Map)
94 import qualified Data.Map.Strict as Map
95 import qualified Data.Map.Strict.Patch as PM
96 import Data.Maybe (fromMaybe)
98 import Data.Ord (Down(..))
99 import Data.Patch.Class (Action(act), Transformable(..), ours)
100 import qualified Data.Set as S
101 import qualified Data.Set as Set
102 import Data.Swagger hiding (version, patch)
103 import Data.Text (Text, isInfixOf, unpack)
104 import Data.Text.Lazy.IO as DTL
105 import Formatting (hprint, int, (%))
106 import Formatting.Clock (timeSpecs)
107 import GHC.Generics (Generic)
108 import Servant hiding (Patch)
109 import System.Clock (getTime, TimeSpec, Clock(..))
110 import Servant.Job.Async (JobFunction(..), serveJobsAPI)
111 import System.IO (stderr)
112 import Test.QuickCheck (elements)
113 import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
115 import Prelude (error)
116 import Gargantext.Prelude hiding (log)
118 import Gargantext.API.Admin.Orchestrator.Types (JobLog(..), AsyncJobs)
119 import Gargantext.API.Admin.Types (HasSettings)
120 import qualified Gargantext.API.Metrics as Metrics
121 import Gargantext.API.Ngrams.Types
122 import Gargantext.API.Prelude
123 import Gargantext.Core.Types (ListType(..), NodeId, ListId, DocId, Limit, Offset, TODO, assertValid)
124 import Gargantext.Core.Utils (something)
125 -- import Gargantext.Core.Viz.Graph.API (recomputeGraph)
126 -- import Gargantext.Core.Viz.Graph.Distances (Distance(Conditional))
127 import Gargantext.Database.Action.Flow.Types
128 import Gargantext.Database.Action.Metrics.NgramsByNode (getOccByNgramsOnlyFast')
129 import Gargantext.Database.Admin.Config (userMaster)
130 import Gargantext.Database.Admin.Types.Node (NodeType(..))
131 import Gargantext.Database.Prelude (HasConnectionPool, HasConfig)
132 import Gargantext.Database.Query.Table.Node.Error (HasNodeError)
133 import Gargantext.Database.Query.Table.Node.Select
134 import Gargantext.Database.Query.Table.Ngrams hiding (NgramsType(..), ngrams, ngramsType, ngrams_terms)
135 import qualified Gargantext.Database.Query.Table.Ngrams as TableNgrams
136 import Gargantext.Database.Query.Table.Node (getNode)
137 import Gargantext.Database.Schema.Node (node_id, node_parentId, node_userId)
138 import Gargantext.Prelude.Job
141 -- TODO sequences of modifications (Patchs)
142 type NgramsIdPatch = Patch NgramsId NgramsPatch
144 ngramsPatch :: Int -> NgramsPatch
145 ngramsPatch n = NgramsPatch (DM.fromList [(1, StopTerm)]) (Set.fromList [n]) Set.empty
147 toEdit :: NgramsId -> NgramsPatch -> Edit NgramsId NgramsPatch
148 toEdit n p = Edit n p
149 ngramsIdPatch :: Patch NgramsId NgramsPatch
150 ngramsIdPatch = fromList $ catMaybes $ reverse [ replace (1::NgramsId) (Just $ ngramsPatch 1) Nothing
151 , replace (1::NgramsId) Nothing (Just $ ngramsPatch 2)
152 , replace (2::NgramsId) Nothing (Just $ ngramsPatch 2)
155 -- applyPatchBack :: Patch -> IO Patch
156 -- isEmptyPatch = Map.all (\x -> Set.isEmpty (add_children x) && Set.isEmpty ... )
158 ------------------------------------------------------------------------
159 ------------------------------------------------------------------------
160 ------------------------------------------------------------------------
163 -- TODO: Replace.old is ignored which means that if the current list
164 -- `MapTerm` and that the patch is `Replace CandidateTerm StopTerm` then
165 -- the list is going to be `StopTerm` while it should keep `MapTerm`.
166 -- However this should not happen in non conflicting situations.
167 mkListsUpdate :: NgramsType -> NgramsTablePatch -> [(NgramsTypeId, NgramsTerm, ListTypeId)]
168 mkListsUpdate nt patches =
169 [ (ngramsTypeId nt, ng, listTypeId lt)
170 | (ng, patch) <- patches ^.. ntp_ngrams_patches . ifolded . withIndex
171 , lt <- patch ^.. patch_list . new
174 mkChildrenGroups :: (PatchSet NgramsTerm -> Set NgramsTerm)
177 -> [(NgramsTypeId, NgramsParent, NgramsChild)]
178 mkChildrenGroups addOrRem nt patches =
179 [ (ngramsTypeId nt, parent, child)
180 | (parent, patch) <- patches ^.. ntp_ngrams_patches . ifolded . withIndex
181 , child <- patch ^.. patch_children . to addOrRem . folded
185 ------------------------------------------------------------------------
187 saveRepo :: ( MonadReader env m, MonadBase IO m, HasRepoSaver env )
189 saveRepo = liftBase =<< view repoSaver
191 listTypeConflictResolution :: ListType -> ListType -> ListType
192 listTypeConflictResolution _ _ = undefined -- TODO Use Map User ListType
194 ngramsStatePatchConflictResolution
195 :: TableNgrams.NgramsType
198 -> ConflictResolutionNgramsPatch
199 ngramsStatePatchConflictResolution _ngramsType _nodeId _ngramsTerm
200 = (ours, (const ours, ours), (False, False))
201 -- (False, False) mean here that Mod has always priority.
202 -- (True, False) <- would mean priority to the left (same as ours).
204 -- undefined {- TODO think this through -}, listTypeConflictResolution)
207 -- Insertions are not considered as patches,
208 -- they do not extend history,
209 -- they do not bump version.
210 insertNewOnly :: a -> Maybe b -> a
211 insertNewOnly m = maybe m (const $ error "insertNewOnly: impossible")
212 -- TODO error handling
215 -- TODO refactor with putListNgrams
216 copyListNgrams :: RepoCmdM env err m
217 => NodeId -> NodeId -> NgramsType
219 copyListNgrams srcListId dstListId ngramsType = do
221 liftBase $ modifyMVar_ var $
222 pure . (r_state . at ngramsType %~ (Just . f . something))
225 f :: Map NodeId NgramsTableMap -> Map NodeId NgramsTableMap
226 f m = m & at dstListId %~ insertNewOnly (m ^. at srcListId)
228 -- TODO refactor with putListNgrams
229 -- The list must be non-empty!
230 -- The added ngrams must be non-existent!
231 addListNgrams :: RepoCmdM env err m
232 => NodeId -> NgramsType
233 -> [NgramsElement] -> m ()
234 addListNgrams listId ngramsType nes = do
236 liftBase $ modifyMVar_ var $
237 pure . (r_state . at ngramsType . _Just . at listId . _Just <>~ m)
240 m = Map.fromList $ (\n -> (n ^. ne_ngrams, n)) <$> nes
244 rmListNgrams :: RepoCmdM env err m
246 -> TableNgrams.NgramsType
248 rmListNgrams l nt = setListNgrams l nt mempty
250 -- | TODO: incr the Version number
251 -- && should use patch
253 setListNgrams :: RepoCmdM env err m
255 -> TableNgrams.NgramsType
256 -> Map NgramsTerm NgramsRepoElement
258 setListNgrams listId ngramsType ns = do
260 liftBase $ modifyMVar_ var $
264 (at listId .~ ( Just ns))
271 currentVersion :: RepoCmdM env err m
275 r <- liftBase $ readMVar var
276 pure $ r ^. r_version
278 newNgramsFromNgramsStatePatch :: NgramsStatePatch -> [Ngrams]
279 newNgramsFromNgramsStatePatch p =
280 [ text2ngrams (unNgramsTerm n)
281 | (n,np) <- p ^.. _PatchMap . each . _PatchMap . each . _NgramsTablePatch . _PatchMap . ifolded . withIndex
282 , _ <- np ^.. patch_new . _Just
285 -- tableNgramsPut :: (HasInvalidError err, RepoCmdM env err m)
286 commitStatePatch :: RepoCmdM env err m => Versioned NgramsStatePatch -> m (Versioned NgramsStatePatch)
287 commitStatePatch (Versioned p_version p) = do
289 vq' <- liftBase $ modifyMVar var $ \r -> do
291 q = mconcat $ take (r ^. r_version - p_version) (r ^. r_history)
292 (p', q') = transformWith ngramsStatePatchConflictResolution p q
293 r' = r & r_version +~ 1
295 & r_history %~ (p' :)
297 -- Ideally we would like to check these properties. However:
298 -- * They should be checked only to debug the code. The client data
299 -- should be able to trigger these.
300 -- * What kind of error should they throw (we are in IO here)?
301 -- * Should we keep modifyMVar?
302 -- * Should we throw the validation in an Exception, catch it around
303 -- modifyMVar and throw it back as an Error?
304 assertValid $ transformable p q
305 assertValid $ applicable p' (r ^. r_state)
307 pure (r', Versioned (r' ^. r_version) q')
312 -- This is a special case of tableNgramsPut where the input patch is empty.
313 tableNgramsPull :: RepoCmdM env err m
315 -> TableNgrams.NgramsType
317 -> m (Versioned NgramsTablePatch)
318 tableNgramsPull listId ngramsType p_version = do
320 r <- liftBase $ readMVar var
323 q = mconcat $ take (r ^. r_version - p_version) (r ^. r_history)
324 q_table = q ^. _PatchMap . at ngramsType . _Just . _PatchMap . at listId . _Just
326 pure (Versioned (r ^. r_version) q_table)
328 -- Apply the given patch to the DB and returns the patch to be applied on the
331 tableNgramsPut :: ( FlowCmdM env err m
336 -> Versioned NgramsTablePatch
337 -> m (Versioned NgramsTablePatch)
338 tableNgramsPut tabType listId (Versioned p_version p_table)
339 | p_table == mempty = do
340 let ngramsType = ngramsTypeFromTabType tabType
341 tableNgramsPull listId ngramsType p_version
344 let ngramsType = ngramsTypeFromTabType tabType
345 (p0, p0_validity) = PM.singleton listId p_table
346 (p, p_validity) = PM.singleton ngramsType p0
348 assertValid p0_validity
349 assertValid p_validity
351 ret <- commitStatePatch (Versioned p_version p)
352 <&> v_data %~ (view (_PatchMap . at ngramsType . _Just . _PatchMap . at listId . _Just))
357 tableNgramsPostChartsAsync :: ( FlowCmdM env err m
361 => UpdateTableNgramsCharts
364 tableNgramsPostChartsAsync utn logStatus = do
365 let tabType = utn ^. utn_tab_type
366 let listId = utn ^. utn_list_id
368 node <- getNode listId
369 let nId = node ^. node_id
370 _uId = node ^. node_userId
371 mCId = node ^. node_parentId
373 printDebug "[tableNgramsPut] tabType" tabType
374 printDebug "[tableNgramsPut] listId" listId
378 printDebug "[tableNgramsPut] can't update charts, no parent, nId" nId
379 pure $ jobLogFail $ jobLogInit 1
383 -- printDebug "[tableNgramsPut] Authors, updating Pie, cId" cId
384 (logRef, logRefSuccess, getRef) <- runJobLog 1 logStatus
386 _ <- Metrics.updatePie cId (Just listId) tabType Nothing
391 -- printDebug "[tableNgramsPut] Institutes, updating Tree, cId" cId
392 -- printDebug "[tableNgramsPut] updating tree StopTerm, cId" cId
393 (logRef, logRefSuccess, getRef) <- runJobLog 3 logStatus
395 _ <- Metrics.updateTree cId (Just listId) tabType StopTerm
396 -- printDebug "[tableNgramsPut] updating tree CandidateTerm, cId" cId
398 _ <- Metrics.updateTree cId (Just listId) tabType CandidateTerm
399 -- printDebug "[tableNgramsPut] updating tree MapTerm, cId" cId
401 _ <- Metrics.updateTree cId (Just listId) tabType MapTerm
406 -- printDebug "[tableNgramsPut] Sources, updating chart, cId" cId
407 (logRef, logRefSuccess, getRef) <- runJobLog 1 logStatus
409 _ <- Metrics.updatePie cId (Just listId) tabType Nothing
414 -- printDebug "[tableNgramsPut] Terms, updating Metrics (Histo), cId" cId
415 (logRef, logRefSuccess, getRef) <- runJobLog 6 logStatus
417 _ <- Metrics.updateChart cId (Just listId) tabType Nothing
419 _ <- Metrics.updatePie cId (Just listId) tabType Nothing
421 _ <- Metrics.updateScatter cId (Just listId) tabType Nothing
423 _ <- Metrics.updateTree cId (Just listId) tabType StopTerm
425 _ <- Metrics.updateTree cId (Just listId) tabType CandidateTerm
427 _ <- Metrics.updateTree cId (Just listId) tabType MapTerm
432 printDebug "[tableNgramsPut] no update for tabType = " tabType
433 pure $ jobLogFail $ jobLogInit 1
436 { _ne_list :: ListType
437 If we merge the parents/children we can potentially create cycles!
438 , _ne_parent :: Maybe NgramsTerm
439 , _ne_children :: MSet NgramsTerm
443 getNgramsTableMap :: RepoCmdM env err m
445 -> TableNgrams.NgramsType
446 -> m (Versioned NgramsTableMap)
447 getNgramsTableMap nodeId ngramsType = do
449 repo <- liftBase $ readMVar v
450 pure $ Versioned (repo ^. r_version)
451 (repo ^. r_state . at ngramsType . _Just . at nodeId . _Just)
453 dumpJsonTableMap :: RepoCmdM env err m
456 -> TableNgrams.NgramsType
458 dumpJsonTableMap fpath nodeId ngramsType = do
459 m <- getNgramsTableMap nodeId ngramsType
460 liftBase $ DTL.writeFile (unpack fpath) (DAT.encodeToLazyText m)
466 -- | TODO Errors management
467 -- TODO: polymorphic for Annuaire or Corpus or ...
468 -- | Table of Ngrams is a ListNgrams formatted (sorted and/or cut).
469 -- TODO: should take only one ListId
471 getTime' :: MonadBase IO m => m TimeSpec
472 getTime' = liftBase $ getTime ProcessCPUTime
475 getTableNgrams :: forall env err m.
476 (RepoCmdM env err m, HasNodeError err, HasConnectionPool env, HasConfig env)
477 => NodeType -> NodeId -> TabType
478 -> ListId -> Limit -> Maybe Offset
480 -> Maybe MinSize -> Maybe MaxSize
482 -> (NgramsTerm -> Bool)
483 -> m (Versioned NgramsTable)
484 getTableNgrams _nType nId tabType listId limit_ offset
485 listType minSize maxSize orderBy searchQuery = do
488 -- lIds <- selectNodesWithUsername NodeList userMaster
490 ngramsType = ngramsTypeFromTabType tabType
491 offset' = maybe 0 identity offset
492 listType' = maybe (const True) (==) listType
493 minSize' = maybe (const True) (<=) minSize
494 maxSize' = maybe (const True) (>=) maxSize
496 selected_node n = minSize' s
498 && searchQuery (n ^. ne_ngrams)
499 && listType' (n ^. ne_list)
503 selected_inner roots n = maybe False (`Set.member` roots) (n ^. ne_root)
505 ---------------------------------------
506 sortOnOrder Nothing = identity
507 sortOnOrder (Just TermAsc) = List.sortOn $ view ne_ngrams
508 sortOnOrder (Just TermDesc) = List.sortOn $ Down . view ne_ngrams
509 sortOnOrder (Just ScoreAsc) = List.sortOn $ view ne_occurrences
510 sortOnOrder (Just ScoreDesc) = List.sortOn $ Down . view ne_occurrences
512 ---------------------------------------
513 selectAndPaginate :: Map NgramsTerm NgramsElement -> [NgramsElement]
514 selectAndPaginate tableMap = roots <> inners
516 list = tableMap ^.. each
517 rootOf ne = maybe ne (\r -> fromMaybe (panic "getTableNgrams: invalid root") (tableMap ^. at r))
519 selected_nodes = list & take limit_
521 . filter selected_node
522 . sortOnOrder orderBy
523 roots = rootOf <$> selected_nodes
524 rootsSet = Set.fromList (_ne_ngrams <$> roots)
525 inners = list & filter (selected_inner rootsSet)
527 ---------------------------------------
528 setScores :: forall t. Each t t NgramsElement NgramsElement => Bool -> t -> m t
529 setScores False table = pure table
530 setScores True table = do
531 let ngrams_terms = unNgramsTerm <$> (table ^.. each . ne_ngrams)
533 occurrences <- getOccByNgramsOnlyFast' nId
538 liftBase $ hprint stderr
539 ("getTableNgrams/setScores #ngrams=" % int % " time=" % timeSpecs % "\n")
540 (length ngrams_terms) t1 t2
542 occurrences <- getOccByNgramsOnlySlow nType nId
548 setOcc ne = ne & ne_occurrences .~ sumOf (at (unNgramsTerm (ne ^. ne_ngrams)) . _Just) occurrences
550 pure $ table & each %~ setOcc
551 ---------------------------------------
553 -- lists <- catMaybes <$> listsWith userMaster
554 -- trace (show lists) $
555 -- getNgramsTableMap ({-lists <>-} listIds) ngramsType
557 let scoresNeeded = needsScores orderBy
558 tableMap1 <- getNgramsTableMap listId ngramsType
560 tableMap2 <- tableMap1 & v_data %%~ setScores scoresNeeded
561 . Map.mapWithKey ngramsElementFromRepo
563 tableMap3 <- tableMap2 & v_data %%~ fmap NgramsTable
564 . setScores (not scoresNeeded)
567 liftBase $ hprint stderr
568 ("getTableNgrams total=" % timeSpecs
569 % " map1=" % timeSpecs
570 % " map2=" % timeSpecs
571 % " map3=" % timeSpecs
572 % " sql=" % (if scoresNeeded then "map2" else "map3")
574 ) t0 t3 t0 t1 t1 t2 t2 t3
578 scoresRecomputeTableNgrams :: forall env err m. (RepoCmdM env err m, HasNodeError err, HasConnectionPool env, HasConfig env) => NodeId -> TabType -> ListId -> m Int
579 scoresRecomputeTableNgrams nId tabType listId = do
580 tableMap <- getNgramsTableMap listId ngramsType
581 _ <- tableMap & v_data %%~ setScores
582 . Map.mapWithKey ngramsElementFromRepo
586 ngramsType = ngramsTypeFromTabType tabType
588 setScores :: forall t. Each t t NgramsElement NgramsElement => t -> m t
590 let ngrams_terms = unNgramsTerm <$> (table ^.. each . ne_ngrams)
591 occurrences <- getOccByNgramsOnlyFast' nId
596 setOcc ne = ne & ne_occurrences .~ sumOf (at (unNgramsTerm (ne ^. ne_ngrams)) . _Just) occurrences
598 pure $ table & each %~ setOcc
604 -- TODO: find a better place for the code above, All APIs stay here
606 data OrderBy = TermAsc | TermDesc | ScoreAsc | ScoreDesc
607 deriving (Generic, Enum, Bounded, Read, Show)
609 instance FromHttpApiData OrderBy
611 parseUrlPiece "TermAsc" = pure TermAsc
612 parseUrlPiece "TermDesc" = pure TermDesc
613 parseUrlPiece "ScoreAsc" = pure ScoreAsc
614 parseUrlPiece "ScoreDesc" = pure ScoreDesc
615 parseUrlPiece _ = Left "Unexpected value of OrderBy"
618 instance ToParamSchema OrderBy
619 instance FromJSON OrderBy
620 instance ToJSON OrderBy
621 instance ToSchema OrderBy
622 instance Arbitrary OrderBy
624 arbitrary = elements [minBound..maxBound]
626 needsScores :: Maybe OrderBy -> Bool
627 needsScores (Just ScoreAsc) = True
628 needsScores (Just ScoreDesc) = True
629 needsScores _ = False
631 type TableNgramsApiGet = Summary " Table Ngrams API Get"
632 :> QueryParamR "ngramsType" TabType
633 :> QueryParamR "list" ListId
634 :> QueryParamR "limit" Limit
635 :> QueryParam "offset" Offset
636 :> QueryParam "listType" ListType
637 :> QueryParam "minTermSize" MinSize
638 :> QueryParam "maxTermSize" MaxSize
639 :> QueryParam "orderBy" OrderBy
640 :> QueryParam "search" Text
641 :> Get '[JSON] (Versioned NgramsTable)
643 type TableNgramsApiPut = Summary " Table Ngrams API Change"
644 :> QueryParamR "ngramsType" TabType
645 :> QueryParamR "list" ListId
646 :> ReqBody '[JSON] (Versioned NgramsTablePatch)
647 :> Put '[JSON] (Versioned NgramsTablePatch)
649 type RecomputeScoresNgramsApiGet = Summary " Recompute scores for ngrams table"
650 :> QueryParamR "ngramsType" TabType
651 :> QueryParamR "list" ListId
652 :> "recompute" :> Post '[JSON] Int
654 type TableNgramsApiGetVersion = Summary " Table Ngrams API Get Version"
655 :> QueryParamR "ngramsType" TabType
656 :> QueryParamR "list" ListId
657 :> Get '[JSON] Version
659 type TableNgramsApi = TableNgramsApiGet
660 :<|> TableNgramsApiPut
661 :<|> RecomputeScoresNgramsApiGet
662 :<|> "version" :> TableNgramsApiGetVersion
663 :<|> TableNgramsAsyncApi
665 type TableNgramsAsyncApi = Summary "Table Ngrams Async API"
669 :> AsyncJobs JobLog '[JSON] UpdateTableNgramsCharts JobLog
671 getTableNgramsCorpus :: (RepoCmdM env err m, HasNodeError err, HasConnectionPool env, HasConfig env)
678 -> Maybe MinSize -> Maybe MaxSize
680 -> Maybe Text -- full text search
681 -> m (Versioned NgramsTable)
682 getTableNgramsCorpus nId tabType listId limit_ offset listType minSize maxSize orderBy mt =
683 getTableNgrams NodeCorpus nId tabType listId limit_ offset listType minSize maxSize orderBy searchQuery
685 searchQuery (NgramsTerm nt) = maybe (const True) isInfixOf mt nt
687 getTableNgramsVersion :: (RepoCmdM env err m, HasNodeError err, HasConnectionPool env, HasConfig env)
692 getTableNgramsVersion _nId _tabType _listId = currentVersion
694 -- Versioned { _v_version = v } <- getTableNgramsCorpus nId tabType listId 100000 Nothing Nothing Nothing Nothing Nothing Nothing
695 -- This line above looks like a waste of computation to finally get only the version.
696 -- See the comment about listNgramsChangedSince.
699 -- | Text search is deactivated for now for ngrams by doc only
700 getTableNgramsDoc :: (RepoCmdM env err m, HasNodeError err, HasConnectionPool env, HasConfig env)
702 -> ListId -> Limit -> Maybe Offset
704 -> Maybe MinSize -> Maybe MaxSize
706 -> Maybe Text -- full text search
707 -> m (Versioned NgramsTable)
708 getTableNgramsDoc dId tabType listId limit_ offset listType minSize maxSize orderBy _mt = do
709 ns <- selectNodesWithUsername NodeList userMaster
710 let ngramsType = ngramsTypeFromTabType tabType
711 ngs <- selectNgramsByDoc (ns <> [listId]) dId ngramsType
712 let searchQuery (NgramsTerm nt) = flip S.member (S.fromList ngs) nt
713 getTableNgrams NodeDocument dId tabType listId limit_ offset listType minSize maxSize orderBy searchQuery
717 apiNgramsTableCorpus :: ( GargServerC env err m
719 => NodeId -> ServerT TableNgramsApi m
720 apiNgramsTableCorpus cId = getTableNgramsCorpus cId
722 :<|> scoresRecomputeTableNgrams cId
723 :<|> getTableNgramsVersion cId
724 :<|> apiNgramsAsync cId
726 apiNgramsTableDoc :: ( GargServerC env err m
728 => DocId -> ServerT TableNgramsApi m
729 apiNgramsTableDoc dId = getTableNgramsDoc dId
731 :<|> scoresRecomputeTableNgrams dId
732 :<|> getTableNgramsVersion dId
733 :<|> apiNgramsAsync dId
734 -- > index all the corpus accordingly (TODO AD)
736 apiNgramsAsync :: NodeId -> GargServer TableNgramsAsyncApi
737 apiNgramsAsync _dId =
739 JobFunction $ \i log ->
742 printDebug "tableNgramsPostChartsAsync" x
744 in tableNgramsPostChartsAsync i log'
746 -- Did the given list of ngrams changed since the given version?
747 -- The returned value is versioned boolean value, meaning that one always retrieve the
749 -- If the given version is negative then one simply receive the latest version and True.
750 -- Using this function is more precise than simply comparing the latest version number
751 -- with the local version number. Indeed there might be no change to this particular list
752 -- and still the version number has changed because of other lists.
754 -- Here the added value is to make a compromise between precision, computation, and bandwidth:
755 -- * currentVersion: good computation, good bandwidth, bad precision.
756 -- * listNgramsChangedSince: good precision, good bandwidth, bad computation.
757 -- * tableNgramsPull: good precision, good bandwidth (if you use the received data!), bad computation.
758 listNgramsChangedSince :: RepoCmdM env err m
759 => ListId -> TableNgrams.NgramsType -> Version -> m (Versioned Bool)
760 listNgramsChangedSince listId ngramsType version
762 Versioned <$> currentVersion <*> pure True
764 tableNgramsPull listId ngramsType version & mapped . v_data %~ (== mempty)