Skip to content

Commit

Permalink
proof-reading done for the core docs
Browse files Browse the repository at this point in the history
  • Loading branch information
abhi18av committed Aug 28, 2019
1 parent e536183 commit 394edb8
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 89 deletions.
18 changes: 9 additions & 9 deletions docs-src/modules/ROOT/pages/core/async.adoc
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
= Async parsing [[AsyncParsing]]

NOTE: Nowadays the parallel parser is the recommended one to use because of the query
strategy, but all the concepts presented here for async parser also applies to the
strategy, but all the concepts presented here for async parser also apply to the
parallel parser, which is async.

If you want to write parsers to run in Javascript environments, then async operations are the norm. The async
parser is a version of the parser were you can return core async channels from the readers instead of raw
parser is a version of the parser were you can return `core.async` channels from the readers instead of raw
values. This allows for the creation of parsers that do network requests or any other async operation.
The async parser is still semantically a *serial* parser, and it will have the same flow characteristics
of the regular parser (the order or resolution is preserved).
Expand All @@ -30,10 +30,10 @@ The core plugins work normally with the async parser, so error and profiling wil

== Error propagation

When an exception occurs inside a core async channel the error is triggered as part of the channel exception handler.
That doesn't compose very well, and for the parser needs it's better if we have something more like the async/await
pattern used on JS environments. Pathom provides some macros to help making this a simple thing, instead of using
`go` and `<!`, use the `go-catch` and `<?` macros, as in the following example:
When an exception occurs inside a `core.async` channel the error is triggered as part of the channel exception handler.
That doesn't compose very well and for the parser it's better if we have something more like the async/await
pattern available within the JS environments. Pathom provides some macros to facilitate this; instead of using
`go` and `<!`, use the provided `go-catch` and `<?` macros, as shown in the following example:

[source,clojure]
----
Expand All @@ -47,7 +47,7 @@ include::example$com/wsscode/pathom/book/async/error_propagation.cljs[]
<div class="space"></div>
++++

Use `com.wsscode.common.async-clj` for Clojure and `com.wsscode.common.async-cljs` for ClojureScript. If you writing a
Use `com.wsscode.common.async-clj` for Clojure and `com.wsscode.common.async-cljs` for ClojureScript. If you are writing a
cljc file, use the following:

[source,clojure]
Expand All @@ -59,8 +59,8 @@ cljc file, use the following:

== JS Promises

In JS world most of the current async responses comes as promises, you can use the `<!p` macro to read from promises
inside `go` blocks as if they were channels. Example:
In JS world most of the current async responses come as promises, you can use the `<!p` macro to read from promises
inside the `go` blocks as if they were channels. Example:

[source,clojure]
----
Expand Down
18 changes: 9 additions & 9 deletions docs-src/modules/ROOT/pages/core/error-handling.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= Error handling

By default, pathom parser will stop if some exception occurs during the parsing process. This is often undesirable if some node fails you still can return the other ones that succeed. You can use the `error-handler-plugin`. This plugin will wrap each read call with a try-catch block, and in case an error occurs, a value of `::p/reader-error` will be placed in that node, while details of it will go in a separate tree, but at the same path. Better an example to demonstrate:
By default, pathom parser will stop if some exception occurs during the parsing process. This is often undesirable if some node fails you still want to be able to return to the other ones which succeed. You can use the `error-handler-plugin`. This plugin will wrap each read call with a try-catch block and in case an error occurs, a value of `::p/reader-error` will be placed in that node, while details of it will go in a separate tree but at the same path. This is better explained through an example:

[source,clojure]
----
Expand Down Expand Up @@ -35,7 +35,7 @@ By default, pathom parser will stop if some exception occurs during the parsing
; [:go :trigger-error] "class clojure.lang.ExceptionInfo: Error triggered - {:foo \"bar\"}"}}
----

As you can see, when an error occurs, the key `::p/errors` will be added to the returned map, containing the detailed error message indexed by the error path. You can customize how the error is exported in this map by setting the key `::p/process-error` in your environment:
As you can see, when an error occurs the key `::p/errors` will be added to the returned map, containing the detailed error message indexed by the error path. You can customize how the error is exported in this map by setting the key `::p/process-error` in your environment:

[source,clojure]
----
Expand Down Expand Up @@ -87,9 +87,9 @@ As you can see, when an error occurs, the key `::p/errors` will be added to the

== Debugging exceptions

By default Pathom error handler will just return a short error message about the exception,
but to debug you will want the stack trace. To view the stack trace you can use a custom
process-error, this is an example to do in Clojure:
By default, Pathom error handler will just return a short error message about the exception
but to debug, you will want the stack trace. To view the stack trace you can use a custom
`process-error`, this is an example of how to do it in Clojure:

[source,clojure]
----
Expand Down Expand Up @@ -127,7 +127,7 @@ In ClojureScript:

== Fail fast

Having each node being caught is great for the UI, but not so much for testing. During testing you probably prefer the parser to blow up as fast as possible so you don't accumulate a bunch of errors that get impossible to read. Having to create a different parser to remove the `error-handler-plugin` can be annoying, so there is an option to solve that. Send the key `::p/fail-fast?` as true in the environment, and the try/catch will not be done, making it fail as soon as an exception fires, for example, using our previous parser:
Having each node being caught is great for the UI, but not so much for testing. During testing you probably prefer the parser to blow up as fast as possible so you don't accumulate a bunch of errors which get impossible to read. Having to create a different parser to remove the `error-handler-plugin` can be annoying, so there is an option to solve that. Send the key `::p/fail-fast?` as true in the environment and the try/catch will not be done, making it fail as soon as an exception fires. For example, using our previous parser:

[source,clojure]
----
Expand All @@ -142,9 +142,9 @@ WARNING: Fail fast doesn't work with parallel parsers
== Raising errors

The default error output format (in a separated tree) is very convenient for direct API
calls, because they leave a clean output on the data part. But if you want to expose those
errors on the UI, pulling then out of the separated tree can be a bit of a pain. To help
with that there is a `p/raise-errors` helper, this will lift the errors so they are present
calls because it leaves a clean output on the data part. But if you want to expose those
errors on the UI, pulling them out of the separated tree can be a bit of a pain. To help
with that, there is a `p/raise-errors` helper which will lift the errors so they are present
at the same level of the error entry. Let's take our last error output example and process
it with `p/raise-errors`

Expand Down
20 changes: 10 additions & 10 deletions docs-src/modules/ROOT/pages/core/getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

== Query Notation Introduction

A query is a vector that lists the items you want. A keyword requests a scalar (opaque) value, and
A `query` is a vector that lists the items you want. A keyword requests a scalar (opaque) value, and
a map indicates a to-many or to-one join (resolved at runtime using database content).

Queries are always "relative" to some starting context (which is typically supplied via parameters
Expand Down Expand Up @@ -41,12 +41,12 @@ is the job of a query parser/interpreter. This library gives you tools for quick

== Parsing Context

The elements of a graph query are relative: they have a contextual meaning. If you ask for a person's name, the implication
The elements of a graph query are relative, which means, they have a contextual meaning. If you ask for a person's name, the implication
is that you are querying a "person entity"; however, the other required bit of information is *which person*. Thus,
elements of a query cannot be fulfilled they are rooted in a context. This applies to joins as well (e.g. what is the current person's
address?), but once you've resolved the context of the *root* of some graph query the joins simply describe navigation
address?); however, once you've resolved the context of the *root* of some graph query the joins simply describe navigation
from *that context* (the person) to another (their address) via a relation that is either already described in the underlying
data source itself, or in code you provide that can figure it out.
data source itself or within the code you provided, that can figure it out.

As the parser moves through a query like `[:person/name {:person/address [:address/street]}]` it first starts
with some context (e.g. "Sam"). When it finds a join it processes the subquery against a new context (e.g. Sam's address)
Expand All @@ -62,19 +62,19 @@ of the query.

== Parsing Environment and The Reader

The parsing environment is simply a map that carries along data while parsing (and can be <<updating-env,augmented as you go>>). It
establishes the meaning of the "current context", can contain anything you wish (via namespaced keywords), and can be
seen in any code that you plug in to process the query.
The parsing environment is simply a map that carries along with it some data while parsing (and can be <<updating-env,augmented as you go>>). It
establishes the meaning of the "current context", containing anything you wish (via namespaced keywords) and can be
seen in any code that you plug-in to process the query.

There are some predefined (namespaced) keys that have special meaning to the parser. In particular
There are some pre-defined (namespaced) keys which have special meaning to the parser. In particular
`:com.wsscode.pathom.core/reader` can be used to supply reader(s) for the parser to use. The `reader` can be a map from
attributes to functions, a plain function, or even a vector of functions. It is asked to read the value for the elements
of the query using the current environment. We'll expand on that as we go, or you can read more in the <<Readers,Readers section>>.
of the query using the current environment. We'll expand on that as we go or you can read more in the <<Readers,Readers section>>.

=== Updating the environment in mid-query [[updating-env]]

During the process of joins it's possible to modify the environment map that will be used
when processing the join. To do that you must return the key `::p/env` with the new full
when processing the join. To do that, you must return the key `::p/env` with the new full
environment. As in this example:

[source,clojure]
Expand Down
54 changes: 27 additions & 27 deletions docs-src/modules/ROOT/pages/core/parsers.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
Parsers are at the core of what Pathom does. This section explains how Pathom parsers
accomplish this responsibility and describes how they work.

== The parser job
== The parser's job

Every EQL transaction is a vector, this means that, by definition, an EQL transaction is
a collection of things. The parser's job is to walk this collection, figures the value
Every EQL transaction is a vector, which means by definition, an EQL transaction is
a collection of things. The parser's job is to walk this collection, figuring out the value
of each requested entry and return a map with them.

In case of Pathom parsers they also have a distinction between `read` and `mutate`, when
the parser is built those are provided separate.
In case of Pathom parsers, they also have a distinction between `read` and `mutate`, when
the parser is built those are provided separately.

I may look like a simple task, but it can get quite complicated depending on how you
intend to coordinate that processing. Let's take a look at the built in parsers from
It may look like a simple task but it can get quite complicated depending on how you
intend to coordinate that processing. Let's take a look at the built-in parsers from
Pathom:

== Serial parser

This is the simplest parser available, it doesn't do more than a reduce, calling the reader
This is the simplest parser available as it doesn't do anything more than a reduce, calling the reader
for each entry in the query.

Just for improve understand, this is how we can implement a simple naive serial parser:
For the sake of understanding, let's see how we can implement a simple naive serial parser:

[source,clojure]
----
Expand All @@ -46,10 +46,10 @@ Now let's push a different query to our parser, adding a parameter to our entry:
; => {(:answer {:with "param"}) nil}
----

So that didn't go so well, we got now a key out that includes the list, and no value.
So, that didn't go so well; we got now a key out that includes the list and no value.

We could deal with this manually, checking for the list, but EQL has enough syntax that
this turns in trouble quickly. To fix this, instead of deal with the EQL directly, let's
We could deal with this manually, checking for the list; but EQL has enough syntax that
this turns in trouble quickly. To fix this, instead of dealing with the EQL directly, let's
convert it to the link:https://edn-query-language.org/eql/1.0.0/specification.html[AST]
format and process that:

Expand All @@ -76,7 +76,7 @@ You may be thinking: what about nested queries?

And the answer is: the parser has nothing to do with that; let's understand why.

Compare these two queries:
Let's compare these two queries:

[source,clojure]
----
Expand All @@ -87,20 +87,20 @@ Compare these two queries:
{:b [:c]}]
----

How many elements each query have? And the answer is two, for both. It just
How many elements each query have? The answer is two, for both. It just
happens that in the second query, the second element is a join; but from the
parser's point of view, in the first case it gets `:a` and `:b`, while in
the second case it gets `:a` and `{:b [:c]}`.
parser's point of view, in the first case it gets `:a` and `:b` while in
the second case it gets an `:a` and `{:b [:c]}`.

That's the reason why it's not valid to do multiple joins in the same map in EQL,
the map itself is considered one entry, because the parser sees it as one element.
the map itself is considered one entry because the parser sees it as one element.

Pathom processes sub-queries at the reader level. The reader can look at the
AST and see that element has `:children`, then it calls the parser again with the
children (and usually with some modifications to the environment) to process that
sub query.
sub-query.

To illustrate how the processing works, let's use Pathom parser again:
To illustrate how this processing works, let's use the Pathom parser again:

[source,clojure]
----
Expand All @@ -126,8 +126,8 @@ and return its value, no matter what you ask, you can try it:
<div class="space"></div>
++++

Notice that if you do queries with joins, they will just be ignored, the reader returns
the value immediately. If we like to increase the counter only on the leaves, we can leverage
Notice that if you do queries with joins, they will just be ignored since the reader returns
the value immediately. If we'd like to increase the counter only on the leaves, we can leverage
Pathom xref:core/readers.adoc#vector-dispatcher[reader composition] and put something before just to walk the joins.

[source,clojure]
Expand All @@ -137,12 +137,12 @@ include::example$com/wsscode/pathom/book/core/parser_counter_nested_example.cljs

[NOTE]
====
For our purposes `p/join` could be replace with a direct recursive call to the parser (which
is available at env as `:parser`). If you want to understand more about `p/join` check
For our purposes `p/join` could be replaced with a direct recursive call to the parser (which
is available in env as `:parser`). If you want to understand more about `p/join` check
xref:core/entities.adoc#_understanding_joins[core join docs].
====

Play around with the following example and see the ordering in which Pathom processes
You are encouraged to play around with the following example and understand the ordering in which Pathom processes
the elements:

++++
Expand All @@ -163,13 +163,13 @@ the elements:

[TIP]
====
By the previous description you may have realized, since readers process sub
Through the previous description you may have realized, since readers process sub
queries, the result is a depth first pre-order traversal. To illustrate, think of the query:
`[:a {:b [:c]} :d]`, the read order goes as: image:serial-parser-traverse.png[Serial parser traverse]
====

These are the basics on the serial parser; and here is a list of things the Pathom parser
does on top of was discussed:
These are the basics of the serial parser; and here is a list of things the Pathom parser
does on top of was discussed in the previous section:

* Fill environment with `:ast`, `:parser` (itself) and `:query`
* Support xref:plugins.adoc[plugins]
Expand Down
4 changes: 2 additions & 2 deletions docs-src/modules/ROOT/pages/core/path-track.adoc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
= Path tracking

As you go deep in your parser `pathom` track record of the current path taken, it's
As you go deeper in your parser, `pathom` keeps a record of the current path taken which is
available at `::p/path` at any time. It's a vector containing the current path from the
root, the current main use for it is regarding error reporting and profiling.
root. Currently the main use for it is regarding error reporting and profiling.

[source,clojure]
----
Expand Down
Loading

0 comments on commit 394edb8

Please sign in to comment.