7 changed files with 151 additions and 1 deletions
			
			
		- 
					33cmd/rpdata-server/main.go
- 
					4graph2/graph.go
- 
					11graph2/queries/changes.go
- 
					4graph2/queries/resolver.go
- 
					8graph2/schema/root.gql
- 
					5models/changes/submit.go
- 
					87models/changes/subscribe.go
| @ -0,0 +1,87 @@ | |||
| package changes | |||
| 
 | |||
| import ( | |||
| 	"context" | |||
| 	"sync" | |||
| 
 | |||
| 	"git.aiterp.net/rpdata/api/models" | |||
| ) | |||
| 
 | |||
| var subMutex sync.Mutex | |||
| var subList []*subscription | |||
| 
 | |||
| type subscription struct { | |||
| 	Keys     map[string]bool | |||
| 	Channel  chan<- models.Change | |||
| 	WildCard bool | |||
| } | |||
| 
 | |||
| // Subscribe subscribes to all changes.
 | |||
| func Subscribe(ctx context.Context, keys []models.ChangeKey, wildcard bool) <-chan models.Change { | |||
| 	channel := make(chan models.Change, 64) | |||
| 	sub := &subscription{ | |||
| 		Keys:     make(map[string]bool, len(keys)), | |||
| 		Channel:  channel, | |||
| 		WildCard: wildcard, | |||
| 	} | |||
| 
 | |||
| 	for _, key := range keys { | |||
| 		sub.Keys[mapKey(key)] = true | |||
| 	} | |||
| 
 | |||
| 	subMutex.Lock() | |||
| 	subList = append(subList, sub) | |||
| 	subMutex.Unlock() | |||
| 
 | |||
| 	go func() { | |||
| 		<-ctx.Done() | |||
| 
 | |||
| 		subMutex.Lock() | |||
| 		for i := range subList { | |||
| 			if subList[i] == sub { | |||
| 				subList = append(subList[:i], subList[i+1:]...) | |||
| 			} | |||
| 		} | |||
| 		subMutex.Unlock() | |||
| 	}() | |||
| 
 | |||
| 	return channel | |||
| } | |||
| 
 | |||
| func pushToSubscribers(change models.Change) { | |||
| 	keys := make([]string, len(change.Keys)) | |||
| 	for i := range change.Keys { | |||
| 		keys[i] = mapKey(change.Keys[i]) | |||
| 	} | |||
| 
 | |||
| 	subMutex.Lock() | |||
| SubLoop: | |||
| 	for _, sub := range subList { | |||
| 		if sub.WildCard && change.Listed { | |||
| 			select { | |||
| 			case sub.Channel <- change: | |||
| 			default: | |||
| 			} | |||
| 		} else { | |||
| 			for _, key := range keys { | |||
| 				if sub.Keys[key] { | |||
| 					select { | |||
| 					case sub.Channel <- change: | |||
| 					default: | |||
| 					} | |||
| 
 | |||
| 					continue SubLoop | |||
| 				} | |||
| 			} | |||
| 		} | |||
| 	} | |||
| 	subMutex.Unlock() | |||
| } | |||
| 
 | |||
| func mapKey(ck models.ChangeKey) string { | |||
| 	return ck.Model.String() + "." + ck.ID | |||
| } | |||
| 
 | |||
| func init() { | |||
| 	subList = make([]*subscription, 0, 16) | |||
| } | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue