mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-03-15 11:40:50 +00:00
Run builtin services directly from aqua run
(#552)
This commit is contained in:
parent
5bd30c7918
commit
7b61247ade
@ -20,17 +20,30 @@ import scalajs.js
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
sealed trait AquaPath
|
||||
sealed trait AquaPath {
|
||||
def getPath[F[_]: Async](): F[Path]
|
||||
}
|
||||
|
||||
// Path for package relative files
|
||||
case class PackagePath(path: String) extends AquaPath
|
||||
case class PackagePath(path: String) extends AquaPath {
|
||||
def getPath[F[_]: Async](): F[Path] = PlatformOpts.getPackagePath(path)
|
||||
}
|
||||
|
||||
// Path for absolute or call path relative files
|
||||
case class RelativePath(path: Path) extends AquaPath
|
||||
case class RelativePath(path: Path) extends AquaPath {
|
||||
def getPath[F[_]: Async](): F[Path] = path.pure[F]
|
||||
}
|
||||
|
||||
object PackagePath {
|
||||
// path to a builtin file in aqua package
|
||||
val builtin: PackagePath = PackagePath("../aqua-lib/builtin.aqua")
|
||||
}
|
||||
|
||||
// All info to run any aqua function
|
||||
case class RunInfo(
|
||||
common: GeneralOptions,
|
||||
func: CliFunc,
|
||||
input: AquaPath,
|
||||
input: Option[AquaPath],
|
||||
imports: List[Path] = Nil,
|
||||
argumentGetters: Map[String, VarJson] = Map.empty,
|
||||
services: List[Service] = Nil,
|
||||
@ -50,15 +63,9 @@ class SubCommandBuilder[F[_]: Async](
|
||||
riF.flatMap {
|
||||
case Validated.Valid(ri) =>
|
||||
LogFormatter.initLogger(Some(ri.common.logLevel.compiler))
|
||||
(ri.input match {
|
||||
case PackagePath(p) => PlatformOpts.getPackagePath(p)
|
||||
case RelativePath(p) => p.pure[F]
|
||||
}).flatMap { path =>
|
||||
RunCommand.execRun(
|
||||
ri,
|
||||
path
|
||||
)
|
||||
}
|
||||
RunCommand.execRun(
|
||||
ri
|
||||
)
|
||||
case i @ Validated.Invalid(_) =>
|
||||
i.pure[F]
|
||||
}
|
||||
@ -103,7 +110,7 @@ object SubCommandBuilder {
|
||||
name,
|
||||
header,
|
||||
GeneralOptions.opt.map { c =>
|
||||
RunInfo(c, CliFunc(funcName), path)
|
||||
RunInfo(c, CliFunc(funcName), Some(path))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -19,6 +19,7 @@ import cats.data.Validated.{invalidNec, validNec}
|
||||
import cats.data.{Chain, NonEmptyList, Validated, ValidatedNec}
|
||||
import cats.effect.IO
|
||||
import cats.effect.kernel.{Async, Clock}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.syntax.monad.*
|
||||
@ -27,11 +28,12 @@ import cats.syntax.traverse.*
|
||||
import fs2.io.file.{Files, Path}
|
||||
import scribe.Logging
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.scalajs.js
|
||||
|
||||
// Function compiler
|
||||
class FuncCompiler[F[_]: Files: AquaIO: Async](
|
||||
input: Path,
|
||||
input: Option[AquaPath],
|
||||
imports: List[Path],
|
||||
transformConfig: TransformConfig,
|
||||
withRunImport: Boolean = false
|
||||
@ -46,9 +48,7 @@ class FuncCompiler[F[_]: Files: AquaIO: Async](
|
||||
.fold(
|
||||
contexts
|
||||
.collectFirstSome(_.allFuncs.get(func.name))
|
||||
)(ab =>
|
||||
contexts.collectFirstSome(_.abilities.get(ab).flatMap(_.allFuncs.get(func.name)))
|
||||
)
|
||||
)(ab => contexts.collectFirstSome(_.abilities.get(ab).flatMap(_.allFuncs.get(func.name))))
|
||||
.map(validNec)
|
||||
.getOrElse(
|
||||
Validated.invalidNec[String, FuncArrow](
|
||||
@ -123,28 +123,53 @@ class FuncCompiler[F[_]: Files: AquaIO: Async](
|
||||
}
|
||||
}
|
||||
|
||||
private def compileToContext(
|
||||
path: Path,
|
||||
imports: List[Path],
|
||||
config: AquaCompilerConf = AquaCompilerConf(transformConfig.constantsList)
|
||||
) = {
|
||||
val sources = new AquaFileSources[F](path, imports)
|
||||
CompilerAPI
|
||||
.compileToContext[F, AquaFileError, FileModuleId, FileSpan.F](
|
||||
sources,
|
||||
SpanParser.parser,
|
||||
config
|
||||
)
|
||||
.map(_.leftMap(_.map(_.show)))
|
||||
}
|
||||
|
||||
private def compileBuiltins() = {
|
||||
for {
|
||||
path <- PackagePath.builtin.getPath()
|
||||
context <- compileToContext(path, Nil)
|
||||
} yield {
|
||||
context
|
||||
}
|
||||
}
|
||||
|
||||
// Compile and get only one function
|
||||
def compile(
|
||||
func: CliFunc,
|
||||
jsonServices: List[JsonService]
|
||||
jsonServices: List[JsonService],
|
||||
withBuiltins: Boolean = false
|
||||
): F[ValidatedNec[String, (FuncArrow, List[Service])]] = {
|
||||
for {
|
||||
prelude <- Prelude.init[F](withRunImport)
|
||||
sources = new AquaFileSources[F](input, prelude.importPaths ++ imports)
|
||||
// compile only context to wrap and call function later
|
||||
compileResult <- Clock[F].timed(
|
||||
CompilerAPI
|
||||
.compileToContext[F, AquaFileError, FileModuleId, FileSpan.F](
|
||||
sources,
|
||||
SpanParser.parser,
|
||||
AquaCompilerConf(transformConfig.constantsList)
|
||||
)
|
||||
.map(_.leftMap(_.map(_.show)))
|
||||
)
|
||||
// compile builtins and add it to context
|
||||
builtinsV <-
|
||||
if (withBuiltins) compileBuiltins()
|
||||
else validNec[String, Chain[AquaContext]](Chain.empty).pure[F]
|
||||
compileResult <- input.map { ap =>
|
||||
// compile only context to wrap and call function later
|
||||
Clock[F].timed(ap.getPath().flatMap(p => compileToContext(p, prelude.importPaths ++ imports)))
|
||||
}.getOrElse((Duration.Zero, validNec[String, Chain[AquaContext]](Chain.empty)).pure[F])
|
||||
(compileTime, contextV) = compileResult
|
||||
} yield {
|
||||
logger.debug(s"Compile time: ${compileTime.toMillis}ms")
|
||||
contextV.andThen(c => findFunctionAndServices(c, func, jsonServices))
|
||||
// add builtins to the end of context
|
||||
contextV.andThen(c => builtinsV.map(bc => c ++ bc)) andThen (c =>
|
||||
findFunctionAndServices(c, func, jsonServices)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ object IpfsOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(UploadFuncName, LiteralRaw.quote(path) :: Nil),
|
||||
PackagePath(IpfsAqua)
|
||||
Option(PackagePath(IpfsAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -64,7 +64,7 @@ object DistOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(RemoveFuncName, LiteralRaw.quote(srvId) :: Nil),
|
||||
PackagePath(DistAqua)
|
||||
Option(PackagePath(DistAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -77,7 +77,7 @@ object DistOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(CreateServiceFuncName, LiteralRaw.quote(blueprintId) :: Nil),
|
||||
PackagePath(DistAqua)
|
||||
Option(PackagePath(DistAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -106,7 +106,7 @@ object DistOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(AddBlueprintFuncName, addBlueprintRequestVar :: Nil),
|
||||
PackagePath(DistAqua),
|
||||
Option(PackagePath(DistAqua)),
|
||||
Nil,
|
||||
Map(
|
||||
addBlueprintRequestVar.name -> VarJson(
|
||||
@ -151,7 +151,7 @@ object DistOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(DeployFuncName, args),
|
||||
PackagePath(DistAqua),
|
||||
Option(PackagePath(DistAqua)),
|
||||
Nil,
|
||||
// hack: air cannot use undefined fields, fill undefined arrays with nils
|
||||
Map(srvName -> VarJson(srvArg, c))
|
||||
|
@ -77,7 +77,7 @@ object RemoteInfoOpts {
|
||||
ListInterfacesFuncName,
|
||||
Nil
|
||||
),
|
||||
PackagePath(NetworkAqua)
|
||||
Option(PackagePath(NetworkAqua))
|
||||
)
|
||||
else
|
||||
RunInfo(
|
||||
@ -86,7 +86,7 @@ object RemoteInfoOpts {
|
||||
ListInterfacesByPeerFuncName,
|
||||
peer.map(LiteralRaw.quote).getOrElse(ValueRaw.InitPeerId) :: Nil
|
||||
),
|
||||
PackagePath(NetworkAqua)
|
||||
Option(PackagePath(NetworkAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -99,7 +99,7 @@ object RemoteInfoOpts {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(GetInterfaceFuncName, LiteralRaw.quote(serviceId) :: Nil),
|
||||
PackagePath(NetworkAqua)
|
||||
Option(PackagePath(NetworkAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -112,7 +112,7 @@ object RemoteInfoOpts {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(GetModuleInterfaceFuncName, LiteralRaw.quote(serviceId) :: Nil),
|
||||
PackagePath(NetworkAqua)
|
||||
Option(PackagePath(NetworkAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -64,7 +64,7 @@ object RunCommand extends Logging {
|
||||
*/
|
||||
def run[F[_]: Files: AquaIO: Async](
|
||||
func: CliFunc,
|
||||
input: Path,
|
||||
input: Option[AquaPath],
|
||||
imports: List[Path],
|
||||
runConfig: RunConfig,
|
||||
transformConfig: TransformConfig
|
||||
@ -72,7 +72,7 @@ object RunCommand extends Logging {
|
||||
val funcCompiler = new FuncCompiler[F](input, imports, transformConfig, withRunImport = true)
|
||||
|
||||
for {
|
||||
funcArrowV <- funcCompiler.compile(func, runConfig.jsonServices)
|
||||
funcArrowV <- funcCompiler.compile(func, runConfig.jsonServices, true)
|
||||
callResult <- Clock[F].timed {
|
||||
funcArrowV match {
|
||||
case Validated.Valid((funcCallable, jsonServices)) =>
|
||||
@ -112,7 +112,6 @@ object RunCommand extends Logging {
|
||||
*/
|
||||
def execRun[F[_]: Async](
|
||||
runInfo: RunInfo,
|
||||
inputPath: Path
|
||||
): F[ValidatedNec[String, Unit]] = {
|
||||
val common = runInfo.common
|
||||
LogFormatter.initLogger(Some(common.logLevel.compiler))
|
||||
@ -121,7 +120,7 @@ object RunCommand extends Logging {
|
||||
RunCommand
|
||||
.run[F](
|
||||
runInfo.func,
|
||||
inputPath,
|
||||
runInfo.input,
|
||||
runInfo.imports,
|
||||
RunConfig(common, runInfo.argumentGetters, runInfo.services ++ builtinServices, runInfo.jsonServices, runInfo.pluginsPaths),
|
||||
transformConfig(common.on, common.constants, common.flags.noXor, common.flags.noRelay)
|
||||
|
@ -51,16 +51,19 @@ object RunOpts extends Logging {
|
||||
}
|
||||
|
||||
def runOptsCompose[F[_]: Files: Concurrent]
|
||||
: Opts[F[ValidatedNec[String, (Path, List[Path], FuncWithData, Option[NonEmptyList[JsonService]], List[String])]]] = {
|
||||
: Opts[F[ValidatedNec[String, (Option[AquaPath], List[Path], FuncWithData, Option[NonEmptyList[JsonService]], List[String])]]] = {
|
||||
(
|
||||
AppOpts.inputOpts[F],
|
||||
AppOpts.wrapWithOption(AppOpts.inputOpts[F]),
|
||||
AppOpts.importOpts[F],
|
||||
ArgOpts.funcWithArgsOpt[F],
|
||||
AppOpts.wrapWithOption(JsonService.jsonServiceOpt),
|
||||
AppOpts.wrapWithOption(Plugin.opt)
|
||||
).mapN { case (inputF, importF, funcWithArgsF, jsonServiceOp, pluginsOp) =>
|
||||
for {
|
||||
inputV <- inputF
|
||||
inputV: ValidatedNec[String, Option[AquaPath]] <-
|
||||
inputF.map(_.map(_.map(p => Option(RelativePath(p))))).getOrElse {
|
||||
validNec[String, Option[AquaPath]](None).pure[F]
|
||||
}
|
||||
importV <- importF
|
||||
funcWithArgsV <- funcWithArgsF
|
||||
jsonServiceV <- jsonServiceOp
|
||||
@ -93,7 +96,7 @@ object RunOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
funcWithArgs.func,
|
||||
RelativePath(input),
|
||||
input,
|
||||
imps,
|
||||
funcWithArgs.getters,
|
||||
Nil,
|
||||
|
@ -120,7 +120,7 @@ object ScriptOpts extends Logging {
|
||||
val tConfig = TransformConfig(relayVarName = None, wrapWithXor = false)
|
||||
val funcCompiler =
|
||||
new FuncCompiler[F](
|
||||
input,
|
||||
Option(RelativePath(input)),
|
||||
imports,
|
||||
tConfig,
|
||||
withRunImport = true
|
||||
@ -173,7 +173,7 @@ object ScriptOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(AddFuncName, scriptVar :: intervalArg :: Nil),
|
||||
PackagePath(ScriptAqua),
|
||||
Option(PackagePath(ScriptAqua)),
|
||||
Nil,
|
||||
Map(
|
||||
"script" -> VarJson(
|
||||
@ -227,7 +227,7 @@ object ScriptOpts extends Logging {
|
||||
RunInfo(
|
||||
common,
|
||||
CliFunc(RemoveFuncName, LiteralRaw.quote(scriptId) :: Nil),
|
||||
PackagePath(ScriptAqua)
|
||||
Option(PackagePath(ScriptAqua))
|
||||
)
|
||||
}
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user