fixed installer
This commit is contained in:
parent
99cbc94b2c
commit
1b5fc6bda9
4 changed files with 92 additions and 31 deletions
|
@ -2,6 +2,4 @@ package events
|
||||||
|
|
||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
func HandleFooEvent(ctx context.Context, event any) {
|
func HandleFooEvent(ctx context.Context, event any) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,36 +7,54 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HandlerFunc is the function being called when receiving an event.
|
||||||
|
type HandlerFunc func(context.Context, any)
|
||||||
|
|
||||||
|
// Emit and event to the given topic
|
||||||
|
func Emit(topic string, event any) {
|
||||||
|
stream.emit(topic, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe a HandlerFunc to the given topic.
|
||||||
|
// A Subscription is being returned that can be used
|
||||||
|
// to unsubscribe from the topic.
|
||||||
|
func Subscribe(topic string, h HandlerFunc) Subscription {
|
||||||
|
return stream.subscribe(topic, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsubscribe unsubribes the given Subscription from its topic.
|
||||||
|
func Unsubscribe(sub Subscription) {
|
||||||
|
stream.unsubscribe(sub)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the event stream, cleaning up its resources.
|
||||||
|
func Stop() {
|
||||||
|
stream.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
var stream *eventStream
|
||||||
|
|
||||||
type event struct {
|
type event struct {
|
||||||
topic string
|
topic string
|
||||||
message any
|
message any
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateUserEvent struct{}
|
|
||||||
|
|
||||||
func HandleCreateUserEvent(ctx context.Context, event CreateUserEvent) {}
|
|
||||||
|
|
||||||
// Handler is the function being called when receiving an event.
|
|
||||||
type Handler func(context.Context, any)
|
|
||||||
|
|
||||||
// Subscription represents a handler subscribed to a specific topic.
|
// Subscription represents a handler subscribed to a specific topic.
|
||||||
type Subscription struct {
|
type Subscription struct {
|
||||||
Topic string
|
Topic string
|
||||||
CreatedAt int64
|
CreatedAt int64
|
||||||
Handler Handler
|
Fn HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventStream
|
type eventStream struct {
|
||||||
type EventStream struct {
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
subs map[string][]Subscription
|
subs map[string][]Subscription
|
||||||
eventch chan event
|
eventch chan event
|
||||||
quitch chan struct{}
|
quitch chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New return a new EventStream
|
func newStream() *eventStream {
|
||||||
func New() *EventStream {
|
e := &eventStream{
|
||||||
e := &EventStream{
|
|
||||||
subs: make(map[string][]Subscription),
|
subs: make(map[string][]Subscription),
|
||||||
eventch: make(chan event, 128),
|
eventch: make(chan event, 128),
|
||||||
quitch: make(chan struct{}),
|
quitch: make(chan struct{}),
|
||||||
|
@ -45,7 +63,7 @@ func New() *EventStream {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EventStream) start() {
|
func (e *eventStream) start() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -54,35 +72,32 @@ func (e *EventStream) start() {
|
||||||
case evt := <-e.eventch:
|
case evt := <-e.eventch:
|
||||||
if handlers, ok := e.subs[evt.topic]; ok {
|
if handlers, ok := e.subs[evt.topic]; ok {
|
||||||
for _, sub := range handlers {
|
for _, sub := range handlers {
|
||||||
go sub.Handler(ctx, evt.message)
|
go sub.Fn(ctx, evt.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the EventStream
|
func (e *eventStream) stop() {
|
||||||
func (e *EventStream) Stop() {
|
|
||||||
e.quitch <- struct{}{}
|
e.quitch <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit an event by specifying a topic and an arbitrary data type
|
func (e *eventStream) emit(topic string, v any) {
|
||||||
func (e *EventStream) Emit(topic string, v any) {
|
|
||||||
e.eventch <- event{
|
e.eventch <- event{
|
||||||
topic: topic,
|
topic: topic,
|
||||||
message: v,
|
message: v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subscribe subscribes a handler to the given topic
|
func (e *eventStream) subscribe(topic string, h HandlerFunc) Subscription {
|
||||||
func (e *EventStream) Subscribe(topic string, h Handler) Subscription {
|
|
||||||
e.mu.RLock()
|
e.mu.RLock()
|
||||||
defer e.mu.RUnlock()
|
defer e.mu.RUnlock()
|
||||||
|
|
||||||
sub := Subscription{
|
sub := Subscription{
|
||||||
CreatedAt: time.Now().UnixNano(),
|
CreatedAt: time.Now().UnixNano(),
|
||||||
Topic: topic,
|
Topic: topic,
|
||||||
Handler: h,
|
Fn: h,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := e.subs[topic]; !ok {
|
if _, ok := e.subs[topic]; !ok {
|
||||||
|
@ -94,8 +109,7 @@ func (e *EventStream) Subscribe(topic string, h Handler) Subscription {
|
||||||
return sub
|
return sub
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsubscribe unsubscribes the given Subscription
|
func (e *eventStream) unsubscribe(sub Subscription) {
|
||||||
func (e *EventStream) Unsubscribe(sub Subscription) {
|
|
||||||
e.mu.RLock()
|
e.mu.RLock()
|
||||||
defer e.mu.RUnlock()
|
defer e.mu.RUnlock()
|
||||||
|
|
||||||
|
@ -104,4 +118,11 @@ func (e *EventStream) Unsubscribe(sub Subscription) {
|
||||||
return sub.CreatedAt == e.CreatedAt
|
return sub.CreatedAt == e.CreatedAt
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if len(e.subs[sub.Topic]) == 0 {
|
||||||
|
delete(e.subs, sub.Topic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
stream = newStream()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,36 @@
|
||||||
package event
|
package event
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEventStream(t *testing.T) {
|
func TestEventSubscribeEmit(t *testing.T) {
|
||||||
|
var (
|
||||||
|
expect = 1
|
||||||
|
wg = sync.WaitGroup{}
|
||||||
|
)
|
||||||
|
wg.Add(1)
|
||||||
|
Subscribe("foo.bar", func(_ context.Context, event any) {
|
||||||
|
value, ok := event.(int)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("expected int got %v", reflect.TypeOf(event))
|
||||||
|
}
|
||||||
|
if value != 1 {
|
||||||
|
t.Errorf("expected %d got %d", expect, value)
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
Emit("foo.bar", expect)
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnsubscribe(t *testing.T) {
|
||||||
|
sub := Subscribe("foo.bar", func(_ context.Context, _ any) {})
|
||||||
|
Unsubscribe(sub)
|
||||||
|
if _, ok := stream.subs["foo.bar"]; ok {
|
||||||
|
t.Errorf("expected topic foo.bar to be deleted")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
20
install.go
20
install.go
|
@ -31,16 +31,30 @@ func main() {
|
||||||
|
|
||||||
projectName := args[0]
|
projectName := args[0]
|
||||||
|
|
||||||
clone := exec.Command("git clone " + reponame)
|
// check if gothkit folder already exists, if so, delete
|
||||||
|
fi, err := os.Stat("gothkit")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if fi.IsDir() {
|
||||||
|
fmt.Println("-- deleting gothkit folder cause its already present")
|
||||||
|
if err := os.RemoveAll("gothkit"); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("-- cloning", reponame)
|
||||||
|
clone := exec.Command("git", "clone", reponame)
|
||||||
if err := clone.Run(); err != nil {
|
if err := clone.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("-- rename bootstrap to", projectName)
|
||||||
if err := os.Rename(path.Join("gothkit", bootstrapFolderName), projectName); err != nil {
|
if err := os.Rename(path.Join("gothkit", bootstrapFolderName), projectName); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := filepath.Walk(path.Join(projectName), func(fullPath string, info fs.FileInfo, err error) error {
|
err = filepath.Walk(path.Join(projectName), func(fullPath string, info fs.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -72,5 +86,5 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("project (%s) successfully installed!\n", projectName)
|
fmt.Printf("-- project (%s) successfully installed!\n", projectName)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue