1
0
Fork 0
burlesque/request.go

98 lines
1.5 KiB
Go
Raw Normal View History

2014-07-10 12:19:39 +00:00
package main
import (
2014-07-16 18:57:54 +00:00
"sync"
2014-07-10 12:19:39 +00:00
)
type (
2014-09-09 08:20:40 +00:00
request struct {
queues []string
responseCh chan response
abort chan bool
dead bool
2014-07-10 12:19:39 +00:00
}
2014-09-09 08:20:40 +00:00
response struct {
queue string
message message
2014-07-10 12:19:39 +00:00
}
)
var (
2014-07-16 18:57:54 +00:00
pool struct {
2014-09-09 08:20:40 +00:00
requests []*request
2014-07-16 18:57:54 +00:00
mutex sync.Mutex
}
2014-07-10 12:19:39 +00:00
)
2014-09-09 08:20:40 +00:00
func registerPublication(q string, msg message) bool {
for _, r := range pool.requests {
if r.dead {
2014-07-17 13:22:37 +00:00
continue
}
2014-09-09 08:20:40 +00:00
for _, qname := range r.queues {
2014-07-17 13:22:37 +00:00
if qname == q {
2014-09-09 08:20:40 +00:00
rsp := response{queue: q, message: msg}
ok := r.tryRespond(rsp)
2014-07-17 13:22:37 +00:00
if ok {
return true
}
2014-07-10 12:19:39 +00:00
}
}
}
2014-07-16 17:50:05 +00:00
2014-09-09 08:20:40 +00:00
ok := getQueue(q).push(msg)
2014-07-16 17:50:05 +00:00
return ok
2014-07-10 12:19:39 +00:00
}
2014-09-09 08:20:40 +00:00
func registerSubscription(r *request) {
for _, qname := range r.queues {
q := getQueue(qname)
msg, ok := q.tryFetch(r.abort)
2014-07-12 10:42:26 +00:00
if ok {
2014-09-09 08:20:40 +00:00
rsp := response{queue: qname, message: msg}
ok := r.tryRespond(rsp)
2014-07-17 13:22:37 +00:00
if !ok {
2014-09-09 08:20:40 +00:00
q.push(msg)
2014-07-17 13:22:37 +00:00
}
2014-07-10 12:19:39 +00:00
return
}
}
2014-07-16 18:57:54 +00:00
2014-09-09 08:20:40 +00:00
pool.requests = append(pool.requests, r)
2014-07-17 13:22:37 +00:00
}
2014-09-09 08:20:40 +00:00
func (r *request) tryRespond(rsp response) bool {
2014-07-17 13:22:37 +00:00
okch := make(chan bool)
go func() {
defer func() {
err := recover()
if err != nil { // Panic!
2014-09-09 08:20:40 +00:00
r.dead = true
2014-07-17 13:22:37 +00:00
okch <- false
}
}()
2014-09-09 08:20:40 +00:00
r.responseCh <- rsp // If channel is already closed expect a panic
2014-07-17 13:22:37 +00:00
okch <- true
}()
ok := <-okch
return ok
2014-07-10 12:19:39 +00:00
}
2014-09-09 08:20:40 +00:00
func (r *request) purge() {
2014-07-16 18:57:54 +00:00
pool.mutex.Lock()
defer pool.mutex.Unlock()
2014-09-09 08:20:40 +00:00
r.dead = true
2014-07-16 18:57:54 +00:00
deleted := 0
2014-09-09 08:20:40 +00:00
for i, req := range pool.requests {
if req.dead {
pool.requests = append(pool.requests[:i-deleted], pool.requests[i-deleted+1:]...)
2014-07-16 18:57:54 +00:00
deleted++
2014-07-10 12:19:39 +00:00
}
}
}