Repository navigation
Expand file tree
/
Copy pathmain.go
More file actions
101 lines (91 loc) · 2.79 KB
/
Copy pathmain.go
File metadata and controls
101 lines (91 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// basic exercises the smallest working setup: configure, subscribe, and
// log every parsed message until SIGINT.
//
// Env: TOKEN (required), ENV (integration|test|production; default
// integration).
package main
import (
"context"
"log"
"log/slog"
"os"
"os/signal"
"syscall"
"time"
"github.com/oddin-gg/gosdk"
"github.com/oddin-gg/gosdk/types"
)
func main() {
cfg := gosdk.NewConfig(envOrDie("TOKEN"), parseEnvironment(),
gosdk.WithLogger(slog.Default()),
)
bootCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
c, err := gosdk.New(bootCtx, cfg)
cancel()
if err != nil {
log.Fatalf("gosdk.New: %v", err)
}
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = c.Close(ctx)
}()
// Subscribe's ctx bounds SETUP only (lazy-connect dial, queue
// topology); it does not govern the subscription's lifetime.
subCtx, cancelSub := context.WithTimeout(context.Background(), 30*time.Second)
sub, err := c.Subscribe(subCtx,
gosdk.WithMessageInterest(types.AllMessageInterest),
)
cancelSub()
if err != nil {
log.Fatalf("subscribe: %v", err)
}
go func() {
// SessionMessage is a tagged union (v2.25): exactly one of
// the embedded EventMessage variants OR UnparsableMessage is
// non-nil per envelope. Branch with simple nil checks.
for msg := range sub.Messages() {
switch {
case msg.OddsChange != nil:
log.Printf("odds change: event=%v markets=%d", msg.OddsChange.Event(), len(msg.OddsChange.Markets()))
case msg.BetSettlement != nil:
log.Printf("settlement: event=%v", msg.BetSettlement.Event())
case msg.BetCancel != nil:
log.Printf("cancel: event=%v", msg.BetCancel.Event())
case msg.UnparsableMessage != nil:
log.Println("unparsable message")
}
}
}()
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
<-sigCh
// Graceful drain BEFORE the deferred client.Close (which is abrupt
// for live subscriptions): sub.Close waits until the consumer
// goroutine above has read every admitted message, then its
// Messages() channel closes, ending that goroutine. See
// examples/graceful for the fully-instrumented version.
drainCtx, cancelDrain := context.WithTimeout(context.Background(), 30*time.Second)
_ = sub.Close(drainCtx)
cancelDrain()
}
func envOrDie(key string) string {
v := os.Getenv(key)
if v == "" {
log.Fatalf("%s not set", key)
}
return v
}
func parseEnvironment() types.Environment {
switch v := os.Getenv("ENV"); v {
case "production":
return types.ProductionEnvironment
case "test":
return types.TestEnvironment
case "integration", "":
return types.IntegrationEnvironment
default:
log.Fatalf("ENV=%q not recognized (want production / test / integration)", v)
return types.UnknownEnvironment // unreachable
}
}