Skip to content

Commit

Permalink
Made Building happen async and in multiple process (#53)
Browse files Browse the repository at this point in the history
* Use startprocess and async to make building faster
* write log file on error
* Logged error files should be chronological.
* Clean up async dispatch for building
  • Loading branch information
beef331 authored Jul 11, 2022
1 parent 280a626 commit 3e6723a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 15 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ docs/*
examplebook/my*
nbook
nbook.exe
x_*
x_*
*.log
50 changes: 36 additions & 14 deletions src/nimibook/builds.nim
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import std / [os, strutils]
import std / [os, strutils, asyncdispatch, osproc, streams, sugar]
import nimibook / [types, commands, themes]
import nimib

proc buildNim*(entry: Entry, srcDir: string, nimOptions: seq[string]): bool =
proc buildNim*(entry: Entry, srcDir: string, nimOptions: seq[string]): Future[bool] {.async.} =
let
cmd = "nim"
args = @["r"] & nimOptions & @[srcDir / entry.path]
# "-d:release", "-f", "--verbosity:0", "--hints:off"
debugEcho "[Executing] ", cmd, " ", args.join(" ")
if execShellCmd(cmd & " " & args.join(" ")) != 0:
echo "[nimibook.error] error while processing ", entry.path
return false
return true

let process = startProcess(cmd, args = args, options = {poUsePath, poStdErrToStdOut})
defer: process.close()
while process.running():
await sleepAsync(10)

result = process.peekexitCode == 0
if not result:
# Process failed so we write a '.log'
let logPath = entry.path.changeFileExt("log")
discard tryRemoveFile(logPath)
let fs = openFileStream(logPath, fmWrite)
defer: fs.close()
for line in process.lines:
fs.writeLine(line)

proc buildMd*(entry: Entry): bool =
try:
Expand All @@ -24,25 +35,36 @@ proc buildMd*(entry: Entry): bool =
echo "[nimibook.error] error while processing ", entry.path
return false

proc build*(entry: Entry, srcDir: string, nimOptions: seq[string]): bool =
proc build*(entry: Entry, srcDir: string, nimOptions: seq[string]): Future[bool] {.async.} =
let splitted = entry.path.splitFile()
if splitted.ext == ".nim":
return buildNim(entry, srcDir, nimOptions)
elif splitted.ext == ".md":
case splitted.ext
of ".nim":
return await buildNim(entry, srcDir, nimOptions)
of ".md":
return buildMd(entry)
else:
echo "[nimibook.error] invalid file extension (must be one of .nim, .md): ", splitted.ext
return false

proc build*(book: Book, nimOptions: seq[string] = @[]) =
var buildErrors: seq[string]
var
buildErrors: seq[string]
buildFutures: seq[Future[bool]]
dump book
for entry in book.toc.entries:
for i in 0..book.toc.entries.high:
let entry = book.toc.entries[i] # use index since `items` returns `lent` in `1.7.x+`
if entry.isDraft:
continue
echo "[nimibook] build entry: ", entry.path
if not build(entry, book.srcDir, nimOptions):
buildErrors.add entry.path
buildFutures.add build(entry, book.srcDir, nimOptions)
closureScope:
let path = entry.path
buildFutures[^1].addCallback do (f: Future[bool]):
if not f.read():
buildErrors.add path

discard waitFor all buildFutures

if len(buildErrors) > 0:
echo "[nimibook.error] ", len(buildErrors), " build errors:"
for err in buildErrors:
Expand Down
1 change: 1 addition & 0 deletions src/nimibook/commands.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import jsony

proc dump*(book: Book) =
var book = book
discard existsOrCreateDir(book.homeDir())
let uri = normalizedPath(book.homeDir / "book.json")
echo "[nimibook] dumping ", uri
writeFile(uri, book.toJson)
Expand Down

0 comments on commit 3e6723a

Please sign in to comment.