Skip to content

Commit 8adef8a

Browse files
committed
feat: can use existing Redis client in the watcher (#59)
1 parent ead01f9 commit 8adef8a

File tree

3 files changed

+162
-2
lines changed

3 files changed

+162
-2
lines changed

README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,97 @@ func main() {
7878

7979
```
8080

81+
## Using Existing Redis Client
82+
83+
If you already have an existing Redis client instance (e.g., due to restricted access to connection details or centralized Redis setup), you can reuse it to create a watcher.
84+
85+
### With Regular Redis Client
86+
87+
```go
88+
package main
89+
90+
import (
91+
"fmt"
92+
93+
"github.com/casbin/casbin/v3"
94+
rediswatcher "github.com/casbin/redis-watcher/v2"
95+
"github.com/redis/go-redis/v9"
96+
)
97+
98+
func main() {
99+
// Create your own Redis client
100+
redisClient := redis.NewClient(&redis.Options{
101+
Addr: "localhost:6379",
102+
Password: "",
103+
DB: 0,
104+
})
105+
106+
// Initialize the watcher with existing client
107+
// Pass empty string for addr since the SubClient and PubClient are already provided
108+
w, _ := rediswatcher.NewWatcher("", rediswatcher.WatcherOptions{
109+
SubClient: redisClient,
110+
PubClient: redisClient,
111+
Channel: "/casbin",
112+
})
113+
114+
// Initialize the enforcer.
115+
e, _ := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
116+
117+
// Set the watcher for the enforcer.
118+
_ = e.SetWatcher(w)
119+
120+
// Set callback
121+
_ = w.SetUpdateCallback(rediswatcher.DefaultUpdateCallback(e))
122+
123+
// Update the policy to test the effect.
124+
_ = e.SavePolicy()
125+
fmt.Scanln()
126+
}
127+
```
128+
129+
### With Redis Cluster Client
130+
131+
```go
132+
package main
133+
134+
import (
135+
"fmt"
136+
137+
"github.com/casbin/casbin/v3"
138+
rediswatcher "github.com/casbin/redis-watcher/v2"
139+
"github.com/redis/go-redis/v9"
140+
)
141+
142+
func main() {
143+
// Create your own Redis cluster client
144+
clusterClient := redis.NewClusterClient(&redis.ClusterOptions{
145+
Addrs: []string{"localhost:7000", "localhost:7001", "localhost:7002"},
146+
Password: "",
147+
})
148+
149+
// Initialize the watcher with existing cluster client
150+
// Pass empty string for addrs since the SubClient and PubClient are already provided
151+
w, _ := rediswatcher.NewWatcherWithCluster("", rediswatcher.WatcherOptions{
152+
SubClient: clusterClient,
153+
PubClient: clusterClient,
154+
Channel: "/casbin",
155+
})
156+
157+
// Initialize the enforcer.
158+
e, _ := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
159+
160+
// Set the watcher for the enforcer.
161+
_ = e.SetWatcher(w)
162+
163+
// Set callback
164+
_ = w.SetUpdateCallback(rediswatcher.DefaultUpdateCallback(e))
165+
166+
// Update the policy to test the effect.
167+
_ = e.SavePolicy()
168+
fmt.Scanln()
169+
}
170+
```
171+
81172
## Getting Help
82173

83174
- [Casbin](https://github.com/casbin/casbin)

options.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
type WatcherOptions struct {
99
Options rds.Options
1010
ClusterOptions rds.ClusterOptions
11-
SubClient *rds.Client
12-
PubClient *rds.Client
11+
SubClient rds.UniversalClient
12+
PubClient rds.UniversalClient
1313
Channel string
1414
IgnoreSelf bool
1515
LocalID string

watcher_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/casbin/casbin/v3"
1212
"github.com/casbin/casbin/v3/persist"
1313
rediswatcher "github.com/casbin/redis-watcher/v2"
14+
"github.com/redis/go-redis/v9"
1415
)
1516

1617
func initWatcherWithOptions(t *testing.T, wo rediswatcher.WatcherOptions, cluster ...bool) (*casbin.Enforcer, *rediswatcher.Watcher) {
@@ -314,3 +315,71 @@ func TestUpdateForUpdatePolicies(t *testing.T) {
314315
w2.Close()
315316
time.Sleep(time.Millisecond * 500)
316317
}
318+
319+
func TestNewWatcherWithClusterUsingExistingClient(t *testing.T) {
320+
// Create a regular Redis client that implements UniversalClient interface
321+
// In production, this would be a cluster client
322+
redisClient := redis.NewClient(&redis.Options{
323+
Addr: "127.0.0.1:6379",
324+
})
325+
326+
// Use the existing client for both pub and sub
327+
// This demonstrates that UniversalClient type works with any Redis client type
328+
wo := rediswatcher.WatcherOptions{
329+
SubClient: redisClient,
330+
PubClient: redisClient,
331+
}
332+
333+
// Initialize watcher with existing client
334+
// Pass empty string for addrs since we're using existing clients
335+
// When SubClient and PubClient are provided, the addrs parameter is ignored
336+
w, err := rediswatcher.NewWatcherWithCluster("", wo)
337+
if err != nil {
338+
t.Fatalf("Failed to create watcher with existing client: %v", err)
339+
}
340+
watcher := w.(*rediswatcher.Watcher)
341+
342+
// Verify the watcher works
343+
_ = watcher.SetUpdateCallback(func(s string) {
344+
t.Log("Received update:", s)
345+
})
346+
347+
_ = watcher.Update()
348+
time.Sleep(time.Millisecond * 500)
349+
350+
watcher.Close()
351+
time.Sleep(time.Millisecond * 500)
352+
}
353+
354+
func TestNewWatcherWithExistingClient(t *testing.T) {
355+
// Create a regular Redis client externally
356+
redisClient := redis.NewClient(&redis.Options{
357+
Addr: "127.0.0.1:6379",
358+
})
359+
360+
// Use the existing client for both pub and sub
361+
wo := rediswatcher.WatcherOptions{
362+
SubClient: redisClient,
363+
PubClient: redisClient,
364+
}
365+
366+
// Initialize watcher with existing client
367+
// Pass empty string for addr since we're using existing clients
368+
// When SubClient and PubClient are provided, the addr parameter is ignored
369+
w, err := rediswatcher.NewWatcher("", wo)
370+
if err != nil {
371+
t.Fatalf("Failed to create watcher with existing client: %v", err)
372+
}
373+
watcher := w.(*rediswatcher.Watcher)
374+
375+
// Verify the watcher works
376+
_ = watcher.SetUpdateCallback(func(s string) {
377+
t.Log("Received update:", s)
378+
})
379+
380+
_ = watcher.Update()
381+
time.Sleep(time.Millisecond * 500)
382+
383+
watcher.Close()
384+
time.Sleep(time.Millisecond * 500)
385+
}

0 commit comments

Comments
 (0)