Thank you @imkleats,
Moving forward, I was thinking about your proposed visitor pattern and had the following considerations:
IMHO, transpilation is the root of all evil. If you cannot fix bugs in the compiler, debugging is doomed. Take it or leave it, but the most pressing pain in JS I had to deal with recently ended up with the transpiler. Source to source re-write is just so fundamentally wrong. I know I am extremely opinionated here, and everyone is free to disagree. However, in Scala, all re-writes were handled in the Compiler by macros for the very specific reason that only that way they could ensure proper AST traversal and emitting proper Bytecode.
In Go, static file generation during the pre-compiler stage nicely integrates through language support to generate code. If you need Go-Bindings to generated files, you just generated & compile the matching bindings...
- Isomorphism simplifies integration. I did the same observation about the similarities between the GraphQL and GraphQL AST.
Honestly, I don't think the neo4j team can do any meaningful re-write of the GRANDstack in Go let alone implementing the visitor pattern anytime soon because well, they, have a job to do. Also, asking for that would be too much of a stretch.
Looking beyond all that, I had recently a fairly radical question:
Why do we need middleware?
We have data, that are graphs, and we have API's, that are graphs.
Expressing one business domain after the other as a sub-graph essentially leaves us with
To make any business domain work, we need, in its purest essence:
With neo4j, we get 1 - 3, but cannot do proper processes across domains. Likewise, with GraphQL, we get 1 - 3 out of the box, but would need to model processes either on the client or on, well, a middleware sitting between the graph and the client.
So what's a process?
A process is a series of steps, with a beginning, a series of steps of which some require sequential execution, other steps can be executed in parallel, and an end.
In its purest essence, a process is a direct acyclic graph, a DAG.
Why, then, don't we store the process in neo4j and expose the process as GraphQL endpoint.
Why, then, we don't write a very thin Go-layer that loads a process through GraphQL from neo4j, executes it according to its structure, and returns the process result again through GraphQL?
Why, then, don't we model Data & relations as GraphQL schema, and then, model work-flows as graphs to connect the different data from the graph?
Why then, don't we just call the process GraphQL with a handful of ID's, let it run the process, and execute it for us?
Why don't we use graph isomorphism in its purest and strictest form to bring a very strong and sound foundation to build stable and reliable software for the 21 Century at the speed of thought?
My humble questions to you are the following:
Do you think it is possible to write a minimal proof of concept in Go that traverses a GraphQL AST, applies the visitor pattern to construct the matching Cypher Query and executes that query?
Do you think a structurally similar approach can be done for loading a process graph from the DB, for which you actually need step 1 to construct the query from the GraphQL schema before executing that query to get a process graph from the DB?
How would you architect a very thin unified data and process layer to build robust systems that concentrate all effort on data & process design while leaving query and execution to the layer?
What would you say are the first critical steps to sustain successful implementation?
and what would you need to get the first critical steps started?