mirror of https://github.com/nealey/microchat.git
Hopefully prevent race conditions
This commit is contained in:
parent
ba2d6a46ad
commit
0fdc23f923
180
microchat.go
180
microchat.go
|
@ -1,105 +1,125 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"log"
|
||||
"time"
|
||||
"strconv"
|
||||
"encoding/json"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
When int64
|
||||
Who string
|
||||
Text string
|
||||
When int64
|
||||
Who string
|
||||
Text string
|
||||
}
|
||||
|
||||
type Forum struct {
|
||||
Name string
|
||||
Log []Message
|
||||
Name string
|
||||
Log []Message
|
||||
SendQ chan Message
|
||||
LogQ chan []Message
|
||||
}
|
||||
|
||||
var foraByName map[string]*Forum
|
||||
|
||||
func (f *Forum) HandleSends() {
|
||||
for m := range f.SendQ {
|
||||
f.Log = append(f.Log, m)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Forum) HandleReads() {
|
||||
for {
|
||||
f.LogQ <- f.Log
|
||||
}
|
||||
}
|
||||
|
||||
func newForum(name string) *Forum {
|
||||
f := &Forum{
|
||||
Name: name,
|
||||
}
|
||||
foraByName[name] = f
|
||||
return f
|
||||
f := &Forum{
|
||||
Name: name,
|
||||
SendQ: make(chan Message, 10),
|
||||
LogQ: make(chan []Message, 10),
|
||||
}
|
||||
go f.HandleSends()
|
||||
go f.HandleReads()
|
||||
|
||||
foraByName[name] = f
|
||||
return f
|
||||
}
|
||||
|
||||
func sayHandler(w http.ResponseWriter, r *http.Request) {
|
||||
message := Message{
|
||||
When: time.Now().Unix(),
|
||||
Who: r.FormValue("who"),
|
||||
Text: r.FormValue("text"),
|
||||
}
|
||||
log.Println(message)
|
||||
forumName := r.FormValue("forum")
|
||||
forum, ok := foraByName[forumName]
|
||||
if !ok {
|
||||
forum = newForum(forumName)
|
||||
}
|
||||
forum.Log = append(forum.Log, message)
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
message := Message{
|
||||
When: time.Now().Unix(),
|
||||
Who: r.FormValue("who"),
|
||||
Text: r.FormValue("text"),
|
||||
}
|
||||
forumName := r.FormValue("forum")
|
||||
f, ok := foraByName[forumName]
|
||||
if !ok {
|
||||
f = newForum(forumName)
|
||||
}
|
||||
f.SendQ <- message
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func readHandler(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
|
||||
forumName := r.FormValue("forum")
|
||||
entriesStr := r.FormValue("entries")
|
||||
|
||||
if entriesStr == "" {
|
||||
entriesStr = "0"
|
||||
}
|
||||
entries, err := strconv.Atoi(entriesStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if entries <= 0 {
|
||||
entries = 20
|
||||
} else if entries > 500 {
|
||||
entries = 500
|
||||
}
|
||||
|
||||
forum, ok := foraByName[forumName]
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
r.ParseForm()
|
||||
|
||||
pos := len(forum.Log) - entries
|
||||
if pos < 0 {
|
||||
pos = 0
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(forum.Log[pos:])
|
||||
forumName := r.FormValue("forum")
|
||||
entriesStr := r.FormValue("entries")
|
||||
|
||||
if entriesStr == "" {
|
||||
entriesStr = "0"
|
||||
}
|
||||
entries, err := strconv.Atoi(entriesStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if entries <= 0 {
|
||||
entries = 20
|
||||
} else if entries > 500 {
|
||||
entries = 500
|
||||
}
|
||||
|
||||
f, ok := foraByName[forumName]
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
log := <-f.LogQ
|
||||
|
||||
pos := len(log) - entries
|
||||
if pos < 0 {
|
||||
pos = 0
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(f.Log[pos:])
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/say", sayHandler)
|
||||
http.HandleFunc("/read", readHandler)
|
||||
http.Handle("/", http.FileServer(http.Dir("static/")))
|
||||
|
||||
foraByName = map[string]*Forum{}
|
||||
f := newForum("")
|
||||
f.Log = []Message{
|
||||
{
|
||||
When: time.Now().Unix(),
|
||||
Who: "(system)",
|
||||
Text: "Welcome to μChat",
|
||||
},
|
||||
}
|
||||
|
||||
bind := ":8080"
|
||||
log.Printf("Listening on %s", bind)
|
||||
log.Fatal(http.ListenAndServe(bind, nil))
|
||||
http.HandleFunc("/say", sayHandler)
|
||||
http.HandleFunc("/read", readHandler)
|
||||
http.Handle("/", http.FileServer(http.Dir("static/")))
|
||||
|
||||
foraByName = map[string]*Forum{}
|
||||
f := newForum("")
|
||||
f.Log = []Message{
|
||||
{
|
||||
When: time.Now().Unix(),
|
||||
Who: "(system)",
|
||||
Text: "Welcome to μChat",
|
||||
},
|
||||
}
|
||||
|
||||
bind := ":8080"
|
||||
log.Printf("Listening on %s", bind)
|
||||
log.Fatal(http.ListenAndServe(bind, nil))
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ body {
|
|||
input[name="who"] {
|
||||
width: 6em;
|
||||
}
|
||||
input[name="text"] {
|
||||
min-width: 30em;
|
||||
width: calc(90% - 6em);
|
||||
}
|
||||
|
||||
.when {
|
||||
color: #888;
|
||||
|
|
|
@ -18,7 +18,6 @@ function μchatInit(initEvent) {
|
|||
let form = event.target
|
||||
let inp = form.elements.text
|
||||
let body = new FormData(form)
|
||||
console.log(form, body)
|
||||
fetch("say", {
|
||||
method: "POST",
|
||||
body: body,
|
||||
|
@ -86,6 +85,9 @@ function μchatInit(initEvent) {
|
|||
.then(updateLog)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
toast("Server error: " + err)
|
||||
})
|
||||
}
|
||||
|
||||
for (let f of document.forms) {
|
||||
|
|
Loading…
Reference in New Issue