working as intended

This commit is contained in:
Maximilian Wagner
2025-12-26 02:50:34 +01:00
parent 6fc4ee2716
commit 8dcf9fba11
5 changed files with 110 additions and 15 deletions

View File

@@ -5,11 +5,13 @@ import (
"errors"
"fmt"
"os"
"io/fs"
"os/exec"
"path/filepath"
"strings"
"time"
"git.noctra.dev/noctra/servtex/globals"
"github.com/fsnotify/fsnotify"
)
// Returns the current time in the timezone specified in the config file
@@ -111,15 +113,89 @@ func ConfigReader(configFileName string, configOptionStorage *globals.Config) er
return err
}
// Contents copied from https://github.com/fsnotify/fsnotify/blob/main/cmd/fsnotify/watch.go
func watchLoop(watcher *fsnotify.Watcher, callOnChange func() error) {
defer watcher.Close()
for {
select {
// Errors
case err, ok := <-watcher.Errors:
if !ok {
LogLine(fmt.Sprintf("Watcher crashed on error, manual compile only: %s", err), 4)
return
}
LogLine(fmt.Sprintf("Watcher Error: %s", err), 3)
// Events
case event, ok := <-watcher.Events:
if !ok {
LogLine(fmt.Sprintf("Watcher crashed on event, manual compile only: %s", event), 4)
return
}
LogLine(fmt.Sprintf("File change noticed: %s", event.Name), 2)
err := callOnChange()
if err != nil {
LogLine(fmt.Sprintf("Latex compilation failed: %s", err), 4)
}
if err = watcher.Add(event.Name); err != nil {
LogLine(fmt.Sprintf("File could not be re-added to watcher: %s", event.Name), 4)
}
}
}
}
func texFinder(path string) []string {
var texFiles []string
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && filepath.Ext(path) == ".tex" {
texFiles = append(texFiles, path)
}
return nil
})
if err != nil {
LogLine("Some paths could not be traversed while search for .tex files", 3)
}
return texFiles
}
// Watches a specified directory and calls a function on change
//
// Optionally, a minimum time to wait for consecutive changes can be specified
func ChangeWatch(path string, callOnChange func()) {
LogLine("File change noticed", 2)
func ChangeWatch(path string, callOnChange func() error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
LogLine("File system watcher could not be initialised, manual compile only", 4)
return
}
for _, file := range texFinder(path) {
if err = watcher.Add(file); err != nil {
LogLine(fmt.Sprintf("File could not be added to watcher: %s", err), 4)
}
LogLine(fmt.Sprintf("File added to watcher: %s", file), 1)
}
go watchLoop(watcher, callOnChange)
LogLine("Watcher initialised", 1)
}
func updateExecutionTimestamp(execution *globals.LatexExecution) {
execution.Timestamp = GetLocalTimePretty()
execution.TimestampRFC = GetLocalTimeRFC()
}
// Intended to be run as goroutine
func LatexCompile(config globals.Config, execution *globals.LatexExecution) error {
func LatexCompile() error {
execution := &globals.LatexExec
config := globals.AppConfig
if execution.ExecutionLock.TryLock() {
defer execution.ExecutionLock.Unlock()
} else {
@@ -143,7 +219,8 @@ func LatexCompile(config globals.Config, execution *globals.LatexExecution) erro
default:
execution.ExecutionState = "Unknown Latex Engine"
execution.Output = []byte{}
execution.Timestamp = GetLocalTimePretty()
updateExecutionTimestamp(execution)
LogLine("Unsupported LaTeX Engine", 4)
return errors.New("Unsupported LaTeX Engine")
}
@@ -156,8 +233,9 @@ func LatexCompile(config globals.Config, execution *globals.LatexExecution) erro
}
execution.Output = stdout
execution.Timestamp = GetLocalTimePretty()
execution.ExecutionState = "Done"
updateExecutionTimestamp(execution)
LogLine("LaTeX execution finished", 2)
return nil
}

View File

@@ -77,16 +77,17 @@ func SSEventHandler(writer http.ResponseWriter, request *http.Request) {
writer.Header().Set("Content-Type", "text/event-stream")
writer.Header().Set("Cache-Control", "no-cache")
writer.Header().Set("Connection", "keep-alive")
ssePing(&writer)
lastExecution := "startup"
for range time.Tick(time.Second) {
if lastExecution == globals.LatexExec.Timestamp {
if lastExecution == globals.LatexExec.TimestampRFC {
ssePing(&writer)
} else {
sseStatusSend(&writer)
ssePDFSend(&writer)
sseOutputSend(&writer)
// comment out for testing purposes
lastExecution = globals.LatexExec.Timestamp
lastExecution = globals.LatexExec.TimestampRFC
}
}
}
@@ -114,6 +115,6 @@ func MainHandler(writer http.ResponseWriter, request *http.Request) {
}
func PDFCompile(writer http.ResponseWriter, request *http.Request) {
backend.LatexCompile(globals.AppConfig, &globals.LatexExec)
backend.LatexCompile()
}

View File

@@ -32,6 +32,7 @@ type LatexExecution struct {
ExecutionLock sync.Mutex
ExecutionState string
Timestamp string
TimestampRFC string
Output []byte
}
var LatexExec LatexExecution

23
main.go
View File

@@ -1,14 +1,16 @@
package main
import (
"os"
"os/signal"
"syscall"
"io/fs"
"context"
"fmt"
"time"
"io/fs"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"git.noctra.dev/noctra/servtex/backend"
"git.noctra.dev/noctra/servtex/frontend"
"git.noctra.dev/noctra/servtex/globals"
@@ -49,6 +51,15 @@ func main() {
if globals.AppConfig.WebserverSecure {
go serverSecure.ListenAndServeTLS(globals.AppConfig.CertificatePath, globals.AppConfig.CertificateKeyPath)
}
// file system change watch
absTexPath, err := filepath.Abs(globals.AppConfig.LatexSourceFilePath)
if err == nil {
backend.ChangeWatch(filepath.Dir(absTexPath), backend.LatexCompile)
} else {
backend.LogLine("Absolute TeX file path could not be gotten", 4)
}
backend.LogLine("Started", 2)
fmt.Println("Press CTRL-C to Exit ServTeX")
@@ -61,7 +72,7 @@ func main() {
fmt.Print("\r")
// shutdown
context, cancel := context.WithTimeout(context.Background(), 15*time.Second)
context, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if err = server.Shutdown(context); err != nil {
backend.LogLine("Graceful Shutdown failed", 4)

View File

@@ -1,4 +1,8 @@
\documentclass{article}
\begin{document}
(This is an Example Document)
Filewatcher Test Document
Filewatcher Test Document
Filewatcher Test Document
Filewatcher Test Document
\end{document}