Restart watches when they stop unexpectedly
This commit is contained in:
+75
-26
@@ -50,8 +50,10 @@ type (
|
|||||||
|
|
||||||
watchSubscription struct {
|
watchSubscription struct {
|
||||||
fission.Watch
|
fission.Watch
|
||||||
kubeWatch watch.Interface
|
kubeWatch watch.Interface
|
||||||
stopped *int32
|
stopped *int32
|
||||||
|
kubernetesClient *kubernetes.Clientset
|
||||||
|
publisher Publisher
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeWatcherRequest struct {
|
kubeWatcherRequest struct {
|
||||||
@@ -135,7 +137,7 @@ func printKubernetesObject(obj runtime.Object, w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kw *KubeWatcher) createKubernetesWatch(w *fission.Watch) (watch.Interface, error) {
|
func createKubernetesWatch(kubeClient *kubernetes.Clientset, w *fission.Watch) (watch.Interface, error) {
|
||||||
var wi watch.Interface
|
var wi watch.Interface
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -144,9 +146,9 @@ func (kw *KubeWatcher) createKubernetesWatch(w *fission.Watch) (watch.Interface,
|
|||||||
// TODO handle the full list of types
|
// TODO handle the full list of types
|
||||||
switch strings.ToUpper(w.ObjType) {
|
switch strings.ToUpper(w.ObjType) {
|
||||||
case "POD":
|
case "POD":
|
||||||
wi, err = kw.kubernetesClient.Core().Pods(w.Namespace).Watch(listOptions)
|
wi, err = kubeClient.Core().Pods(w.Namespace).Watch(listOptions)
|
||||||
case "SERVICE":
|
case "SERVICE":
|
||||||
wi, err = kw.kubernetesClient.Core().Services(w.Namespace).Watch(listOptions)
|
wi, err = kubeClient.Core().Services(w.Namespace).Watch(listOptions)
|
||||||
default:
|
default:
|
||||||
msg := fmt.Sprintf("Error: unknown obj type '%v'", w.ObjType)
|
msg := fmt.Sprintf("Error: unknown obj type '%v'", w.ObjType)
|
||||||
log.Println(msg)
|
log.Println(msg)
|
||||||
@@ -157,18 +159,11 @@ func (kw *KubeWatcher) createKubernetesWatch(w *fission.Watch) (watch.Interface,
|
|||||||
|
|
||||||
func (kw *KubeWatcher) addWatch(w *fission.Watch) error {
|
func (kw *KubeWatcher) addWatch(w *fission.Watch) error {
|
||||||
log.Printf("Adding watch %v: %v", w.Metadata.Name, w.Function.Name)
|
log.Printf("Adding watch %v: %v", w.Metadata.Name, w.Function.Name)
|
||||||
wi, err := kw.createKubernetesWatch(w)
|
ws, err := MakeWatchSubscription(w, kw.kubernetesClient, kw.publisher)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var stopped int32 = 0
|
|
||||||
ws := &watchSubscription{
|
|
||||||
Watch: *w,
|
|
||||||
kubeWatch: wi,
|
|
||||||
stopped: &stopped,
|
|
||||||
}
|
|
||||||
kw.watches[w.Metadata.Uid] = *ws
|
kw.watches[w.Metadata.Uid] = *ws
|
||||||
go ws.eventDispatchLoop(kw.publisher)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,19 +180,73 @@ func (kw *KubeWatcher) removeWatch(w *fission.Watch) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *watchSubscription) eventDispatchLoop(publisher Publisher) {
|
// wi, err := kw.createKubernetesWatch(w)
|
||||||
log.Println("Listening to watch ", ws.Watch.Metadata.Name)
|
// if err != nil {
|
||||||
for {
|
// return err
|
||||||
ev, more := <-ws.kubeWatch.ResultChan()
|
// }
|
||||||
if !more {
|
// var stopped int32 = 0
|
||||||
log.Println("Watch stopped", ws.Watch.Metadata.Name)
|
// ws := &watchSubscription{
|
||||||
break
|
// Watch: *w,
|
||||||
}
|
// kubeWatch: wi,
|
||||||
publisher.Publish(ev, ws.Watch.Target)
|
// stopped: &stopped,
|
||||||
|
// }
|
||||||
|
// kw.watches[w.Metadata.Uid] = *ws
|
||||||
|
// go ws.eventDispatchLoop(kw.publisher)
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
func MakeWatchSubscription(w *fission.Watch, kubeClient *kubernetes.Clientset, publisher Publisher) (*watchSubscription, error) {
|
||||||
|
var stopped int32 = 0
|
||||||
|
ws := &watchSubscription{
|
||||||
|
Watch: *w,
|
||||||
|
kubeWatch: nil,
|
||||||
|
stopped: &stopped,
|
||||||
|
kubernetesClient: kubeClient,
|
||||||
|
publisher: publisher,
|
||||||
}
|
}
|
||||||
if atomic.LoadInt32(ws.stopped) != 0 {
|
|
||||||
// TODO can this happen? How do we start the watch again from the right
|
err := ws.restartWatch()
|
||||||
// point?
|
if err != nil {
|
||||||
log.Panicf("Watch channel closed unexpectedly")
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go ws.eventDispatchLoop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *watchSubscription) restartWatch() error {
|
||||||
|
retries := 60
|
||||||
|
for {
|
||||||
|
wi, err := createKubernetesWatch(kubeClient, w)
|
||||||
|
if err != nil {
|
||||||
|
retries--
|
||||||
|
if retries > 0 {
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws.kubeWatch = wi
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *watchSubscription) eventDispatchLoop() {
|
||||||
|
log.Println("Listening to watch ", ws.Watch.Metadata.Name)
|
||||||
|
for {
|
||||||
|
for {
|
||||||
|
ev, more := <-ws.kubeWatch.ResultChan()
|
||||||
|
if !more {
|
||||||
|
log.Println("Watch stopped", ws.Watch.Metadata.Name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ws.publisher.Publish(ev, ws.Watch.Target)
|
||||||
|
}
|
||||||
|
if atomic.LoadInt32(ws.stopped) == 0 {
|
||||||
|
err := ws.restartWatch()
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("Failed to restart watch: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user