{- Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. -} -- -- | Connecting to a Glean server or a local database store. -- -- Client code that wants to be able to use either a remote -- Glean server or a local database store should look like: -- -- > import Glean -- > import Glean.LocalOrRemote -- > import Glean.Util.ConfigProvider -- > import Glean.Impl.ConfigProvider -- > import Glean.Schema.Builtin.Types (schema_id) -- > import Util.EventBase -- > -- > main :: IO () -- > main = -- > withConfigOptions options $ \(service, cfgOpts) -> -- > withEventBaseDataplane $ \evb -> -- > withConfigProvider cfgOpts $ \(cfgAPI :: ConfigAPI) -> -- > withBackendWithDefaultOptions evb cfgAPI service (Just schema_id) -- > $ \backend -> do -- > ... -- module Glean.LocalOrRemote ( -- * Connecting to a remote server or a local database store options , optionsLong , withBackendWithDefaultOptions , withBackend , defaultClientConfigSource , Service(..) , Logging(..) , LocalOrRemote(..) , LoggingBackend(..) , BackendKind(..) -- * Misc , validate , Validate(..) , dumpJsonToFile , finalize , sendJsonBatch -- * Schemas , loadDbSchema , serializeInventory ) where import Control.Exception import Control.Monad.Extra import qualified Data.ByteString.Char8 as BC import Data.Default import Data.IORef import Options.Applicative as O import System.IO import Text.Printf import Util.EventBase import Glean hiding (finalize) -- we will provide versions of finalize and sendJsonBatch that are -- more efficient with local DBs. import qualified Glean import Glean.Backend.Local hiding (options) import qualified Glean.Backend.Local as Local import Glean.Backend.Logging import Glean.DefaultConfigs import Glean.Dump import Glean.Database.Validate import Glean.Database.Finish (finalizeWait) import qualified Glean.Remote as Remote import Glean.Util.ConfigProvider import qualified Glean.Util.Service as Service import Glean.Util.Some import qualified Glean.Util.ThriftSource as ThriftSource import Glean.Write.JSON (syncWriteJsonBatch) data Logging = EnableLogging | DisableLogging deriving (Eq, Show) -- | Specifies what kind of 'Backend' to construct. data Service = Local Local.Config Logging | Remote (ThriftSource ClientConfig) deriving Show -- | Use the provided 'Service' to make a 'Backend'. (note in fact -- that it provides a 'LocalOrRemote', which is a 'Backend' that -- additionally supports 'backendKind'). withBackendWithDefaultOptions :: ConfigProvider conf => EventBaseDataplane -> conf -> Service -> Maybe SchemaId -> (forall b. LocalOrRemote b => b -> IO a) -> IO a withBackendWithDefaultOptions evb cfgapi service schema = withBackend evb cfgapi service schema id -- | Use the provided 'Service' to make a 'Backend', applying some -- 'Settings' if this is a remote backend. (note in fact that it -- provides a 'LocalOrRemote', which is a 'Backend' that additionally -- supports 'backendKind'). withBackend :: ConfigProvider conf => EventBaseDataplane -> conf -> Service -> Maybe SchemaId -> Remote.Settings -> (forall b. LocalOrRemote b => b -> IO a) -> IO a withBackend evb cfgapi service schema settings inner = case service of Local cfg logging -> let cfg' = cfg { cfgSchemaId = schema } in withDatabases evb cfg' cfgapi $ case logging of EnableLogging -> inner . LoggingBackend DisableLogging -> inner Remote src -> do config <- ThriftSource.loadDefault cfgapi src let (config', opts) = settings (config, def) case Remote.thriftServiceWithTimeout config' opts of Nothing -- The default service is a tier, which is not supported in -- the open-source build. To avoid a confusing error message -- when someone just forgets to use --db-root or --service, -- let's try to be helpful: | clientConfig_serv config' == clientConfig_serv def -> throwIO $ ErrorCall $ "No default Glean service. To use local DBs, " <> "specify --db-root