Skip to content

Commit

Permalink
- Fix for Lifecycle Race Conditions w/Sourcegear
Browse files Browse the repository at this point in the history
- Better Sourcegear reporting tools. see Sourcegear.print
- Removed Put Update Route from REST API -> only availible from the Websockets now
  • Loading branch information
Aidan Cunniffe committed Mar 6, 2018
1 parent 3bd8327 commit 6b40294
Show file tree
Hide file tree
Showing 20 changed files with 118 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object KnowledgeGraphImplicits {
knowledgeGraph
.get(i)
.edges
.filter(e => e.isOut && e.to != this && e.isLabeled && e.label.isInstanceOf[Transformation])
.filter(e => e.isDirected && e.isLabeled && e.from.value == i && e.label.isInstanceOf[Transformation])
.map(i => {
DirectTransformation(i.label.asInstanceOf[Transformation], i.to.value.asInstanceOf[SchemaNode].schema.schemaRef)
}).toSet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.opticdev.parsers.graph.BaseNode
import com.opticdev.sdk.descriptions.Schema

import scalax.collection.GraphEdge.{EdgeLike, UnDiEdge}
import scalax.collection.edge.LkDiEdge
import scalax.collection.immutable.Graph

package object graph {
Expand All @@ -13,6 +14,6 @@ package object graph {
case class SchemaNode(schema: Schema) extends SGNode
case class GearNode(gear: Gear) extends SGNode

type KnowledgeGraph = Graph[SGNode, UnDiEdge]
type KnowledgeGraph = Graph[SGNode, LkDiEdge]

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ object IndexSourceGear {
(inputSchemaNode ~+#> outputSchemaNode)(t)
}.toVector

Graph((schemaGearNodes ++ transformationNodes):_*).asInstanceOf[KnowledgeGraph]
Graph(schemaGearNodes ++ transformationNodes:_*).asInstanceOf[KnowledgeGraph]
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,15 @@ class KnowledgeGraphImplicitsSpec extends TestBase with TestPackageProviders {
assert(results.size == 1)
}

it("will not find the inverse of a transformation") {
val f = fixture
val ref = SchemaRef(PackageRef("optic:test"), "route")

val results = f.knowledgeGraphWithTransformations.availableTransformations(ref)


assert(!results.map(_.transformation.output).contains(SchemaRef(PackageRef("optic:test"), "model")))

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ object SGConstructor {
val failedPackages = compiledPackages.filter(_.isFailure).map(i=> (i.opticPackage, i.errors))
.toMap

println("Compile Errors:")
failedPackages.values.flatMap(_.values).foreach(_.printAll)

throw new SomePackagesFailedToCompile(failedPackages)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ abstract class SourceGear {

def isLoaded : Boolean = true

def print = println(
s"""
| Parsers: ${parsers.map(_.parserRef.full).mkString(",")}
| Schemas: ${schemas.map(_.schemaRef.full).mkString(",")}
| Gears: ${gearSet.listGears.map(_.name).mkString(",")}
| Transformations: ${transformations.map(_.name).mkString(",")}
""".stripMargin)

}

case object UnloadedSourceGear extends SourceGear {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Project(name: String, baseDirectory: File)(implicit logToCli: Boolean = fa
//run all callbacks
sourcegearchangedCallbacks.foreach(_.apply(sourceGear))
projectStatusInstance.sourceGearStatus = Valid
sourceGear.print
if (projectStatus.monitoringStatus == Watching) rereadAll
} else {
println(i.failed.get.printStackTrace())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ object PackageManager {
}

def installPackages(packages: PackageRef*)(implicit projectKnowledgeSearchPaths: ProjectKnowledgeSearchPaths) = Try {

//name -> satisfied
val flattenedDependencyTree = collection.mutable.Map[PackageRef, Boolean]()
packages.foreach(i=> flattenedDependencyTree(i) = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ object OpticPackage {
if (parsedOption.isSuccess /* && parsedOption.get.noErrors */) {
StagedPackage(parsedOption.get.description)
} else {
throw new Error("Invalid Optic Markdown")
throw new Error("Invalid Optic Markdown" + parsedOption.failed.get.toString)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ class LocalProvider extends Provider {
override def listInstalledPackages (implicit projectKnowledgeSearchPaths: ProjectKnowledgeSearchPaths) : Vector[OpticPackage] = {
val allFiles = projectKnowledgeSearchPaths.dirs.flatMap(_.listRecursively)

val allPackages = allFiles.filter(_.extension.orNull == ".md")
val results = allFiles.filter(_.extension.orNull == ".md")
.map(i => OpticPackage.fromMarkdown(i))
.toVector
.collect {
case Success(i) => i
}

//print out failing pacakges
results.collect {
case Failure(i) => println(i)
}

val allPackages = results.collect {
case Success(i) => i
}

allPackages
}
Expand Down
6 changes: 4 additions & 2 deletions sdk/src/main/scala-2.12/com.opticdev/sdk/MarkdownParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ object MarkdownParser {
def noErrors = errors.value.isEmpty
}

private val pathToExecutable = "/usr/local/bin/node /usr/local/lib/node_modules/optic-markdown/lib/cli.js"

def parseMarkdown(file: File) = Try[MDParseOutput] {
//check the version eventually
val version = "optic-md --version" !!
val version = pathToExecutable+ " --version" !!

if (version.contains("not found")) throw new Error("optic-md is not installed. Run npm install optic-md -g")

val result = "optic-md " + file.pathAsString !!
val result = pathToExecutable+ " " + file.pathAsString !!

val parsedJson = Try(Json.parse(result))

Expand Down
26 changes: 13 additions & 13 deletions sdk/src/test/scala-2.12/com/opticdev/sdk/MarkdownParserSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import better.files.File
import org.scalatest.FunSpec

class MarkdownParserSpec extends FunSpec {
//
// it("will succeed if given a valid file") {
// val outputTry = MarkdownParser.parseMarkdown(File("test-examples/resources/example_markdown/Importing-JS.md"))
// assert(outputTry.isSuccess)
// }
//
// it("will fail if given no file") {
// assert(MarkdownParser.parseMarkdown(File("")).isFailure)
// }
//
// it("will fail if given an invalid file") {
// assert(MarkdownParser.parseMarkdown(File("not-real.file")).isFailure)
// }

it("will succeed if given a valid file") {
val outputTry = MarkdownParser.parseMarkdown(File("test-examples/resources/example_markdown/Importing-JS.md"))
assert(outputTry.isSuccess)
}

it("will fail if given no file") {
assert(MarkdownParser.parseMarkdown(File("")).isFailure)
}

it("will fail if given an invalid file") {
assert(MarkdownParser.parseMarkdown(File("not-real.file")).isFailure)
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.opticdev.server.http

import com.opticdev.server.http.routes.{ContextRoute, ProjectRoute, PutUpdateRoute}
import com.opticdev.server.http.routes.{ContextRoute, ProjectRoute}
import akka.http.scaladsl.server.Directives._
import com.opticdev.server.http.routes.socket.SocketRoute
import com.opticdev.server.state.ProjectsManager
Expand All @@ -12,13 +12,13 @@ class HttpService(implicit executionContext: ExecutionContext, projectsManager:
val projectsRoute = new ProjectRoute()
val contextRoute = new ContextRoute()
val editorConnectionRoute = new SocketRoute()
val putUpdateRoute = new PutUpdateRoute()
// val putUpdateRoute = new PutUpdateRoute()

val routes = {
projectsRoute.route ~
editorConnectionRoute.route ~
contextRoute.route ~
putUpdateRoute.route
contextRoute.route
// putUpdateRoute.route
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.opticdev.server.http

import java.io.{BufferedReader, InputStreamReader}

import better.files.File
import com.opticdev.core.sourcegear.project.Project
import com.opticdev.core.sourcegear.project.config.ProjectFile
Expand All @@ -8,18 +10,26 @@ import com.opticdev.opm.providers.LocalProvider
import com.opticdev.opm.storage.{PackageStorage, ParserStorage}
import com.opticdev.parsers.SourceParserManager
import com.opticdev.server.state.ProjectsManager

import scala.io.Source
import scala.util.Try
object Lifecycle extends App {
//@todo load parsers dynamically.
val jar = this.getClass.getClassLoader.getResource("es7_2.12-0.1.0.jar").getFile
val parserBase = Try {
ParserStorage.writeToStorage(File(jar))
SourceParserManager.installParser(jar).get
}.getOrElse {
val withoutFileExtension = jar.substring(5)
val pathAsString = (File(withoutFileExtension).parent.parent / "es7_2.12-0.1.0.jar").pathAsString
ParserStorage.writeToStorage(File(pathAsString))
SourceParserManager.installParser(pathAsString).get
}

PackageStorage.clearLocalPackages

//set the local providers for the OPM
PackageManager.setProviders(new LocalProvider)

//@todo load parsers dynamically.
val jar = this.getClass.getClassLoader.getResource("es7_2.12-0.1.0.jar").getPath
val defaultParserTry = SourceParserManager.installParser(jar)
ParserStorage.writeToStorage(File(jar))

implicit val projectsManager: ProjectsManager = new ProjectsManager()
implicit val actorCluster = projectsManager.actorCluster
//manually adding projects for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ArrowPostChanges(projectName: String, changeGroup: ChangeGroup)(implicit p
import com.opticdev.server.data.ModelNodeJsonImplicits._
stage.transform {
case Success(batchedChanges: BatchedChanges) => {
val updatedFiles = batchedChanges.stagedFiles.keys.map(i=> JsString(i.pathAsString)).toSeq
val updatedFiles: Seq[JsString] = batchedChanges.stagedFiles.keys.map(i=> JsString(i.pathAsString)).toSeq

if (batchedChanges.isSuccess) {
Try(APIResponse(StatusCodes.OK, JsObject(Seq("success" -> JsBoolean(true), "updatedFiles" -> JsArray(updatedFiles)))))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ class ContextQuery(file: File, range: Range, contentsOption: Option[String])(imp
"transformations" -> JsArray(results.availableTransformations.map(_.asJson))
))))
}
case Failure(exception: ServerExceptions) => Try(APIResponse(StatusCodes.NotFound, exception.asJson))
case Failure(exception: ServerExceptions) => {
Try(APIResponse(StatusCodes.NotFound, exception.asJson))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import com.opticdev.server.state.ProjectsManager
import play.api.libs.json.{JsArray, JsObject, JsString}
import com.opticdev.core.sourcegear.mutate.MutationSteps._
import com.opticdev.core.sourcegear.project.OpticProject
import com.opticdev.core.sourcegear.project.monitoring.StagedContent
import com.opticdev.server.data.{APIResponse, ModelNodeWithIdNotFound, ServerExceptions}
import com.opticdev.server.http.routes.socket.editors.Protocol.FilesUpdated

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
Expand All @@ -18,7 +20,7 @@ import scala.util.{Failure, Success, Try}
class PutUpdateRequest(id: String, newValue: JsObject)(implicit projectsManager: ProjectsManager) {


def execute = Future[File] {
def execute = Future[FilesUpdated] {

implicit val actorCluster = projectsManager.actorCluster

Expand All @@ -43,20 +45,23 @@ class PutUpdateRequest(id: String, newValue: JsObject)(implicit projectsManager:

file.write(output)


FilesUpdated(Map(file -> StagedContent(output)))

} else {
throw ModelNodeWithIdNotFound(id)
}

}

def executeToApiResponse : Future[APIResponse] = {

execute.transform {
case Success(file) => {
Try(APIResponse(StatusCodes.OK, JsObject(Seq("filesUpdated" -> JsArray(Seq(JsString(file.pathAsString)))))))
}
case Failure(exception: ServerExceptions) => Try(APIResponse(StatusCodes.NotFound, exception.asJson))
}
}
// def executeToApiResponse : Future[APIResponse] = {
//
// execute.transform {
// case Success(file) => {
// Try(APIResponse(StatusCodes.OK, JsObject(Seq("filesUpdated" -> JsArray(Seq(JsString(file.pathAsString)))))))
// }
// case Failure(exception: ServerExceptions) => Try(APIResponse(StatusCodes.NotFound, exception.asJson))
// }
// }

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ import de.heikoseeberger.akkahttpplayjson.PlayJsonSupport._
import scala.concurrent.ExecutionContext
import scala.util.{Failure, Success}

class PutUpdateRoute(implicit executionContext: ExecutionContext, projectsManager: ProjectsManager) {

val route: Route =
path("models" / Segment) { (modelId) => {
put {
entity(as[JsObject]) { json =>
onComplete(new PutUpdateRequest(modelId, json).executeToApiResponse) {
case Success(value) => complete(value.statusCode, value.data)
case Failure(ex) => complete(StatusCodes.InternalServerError, JsString(s"An error occurred: ${ex.getMessage}"))
}
}
}
}}

}
//class PutUpdateRoute(implicit executionContext: ExecutionContext, projectsManager: ProjectsManager) {
//
// val route: Route =
// path("models" / Segment) { (modelId) => {
// put {
// entity(as[JsObject]) { json =>
// onComplete(new PutUpdateRequest(modelId, json).executeToApiResponse) {
// case Success(value) => complete(value.statusCode, value.data)
// case Failure(ex) => complete(StatusCodes.InternalServerError, JsString(s"An error occurred: ${ex.getMessage}"))
// }
// }
// }
// }}
//
//}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,14 @@ class AgentConnectionActor(slug: String, projectsManager: ProjectsManager) exten
case update : PutUpdate => {
//@todo handle error states
new PutUpdateRequest(update.id, update.newValue)(projectsManager)
.executeToApiResponse
.execute.onComplete(i=> {
if (i.isFailure) {
println(i.failed.get)
} else {
EditorConnection.broadcastUpdate( i.get )
}

})
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,18 @@ class PutUpdateRequestSpec extends AkkaTestFixture("PutUpdateRequest") with Proj

val result = Await.result(future, 3 seconds)

val newContents = result.contentAsString
val newContents = result.fileUpdates.head._2.text
println(newContents)
assert(newContents.contains("app.post('other/url'"))

}

it("can update model and return API request") {
val putUpdate = new PutUpdateRequest(modelId, JsObject(Seq("method" -> JsString("post"), "url" -> JsString("other/url"))))
val future = putUpdate.executeToApiResponse

val future = putUpdate.execute
val result = Await.result(future, 3 seconds)

println(result.data.as[JsObject])

assert(result.statusCode == StatusCodes.OK)
assert(result.data.as[JsObject]
.value("filesUpdated").as[JsArray]
.value.exists(_.as[JsString].value.contains("app.js")))
assert(result.fileUpdates.size == 1)

}

Expand Down

0 comments on commit 6b40294

Please sign in to comment.