github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/rpc/state/subscribe_storage.go (about) 1 // Go Substrate RPC Client (GSRPC) provides APIs and types around Polkadot and any Substrate-based chain RPC calls 2 // 3 // Copyright 2020 Stafi Protocol 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package state 18 19 import ( 20 "context" 21 "sync" 22 23 "github.com/stafiprotocol/go-substrate-rpc-client/config" 24 gethrpc "github.com/stafiprotocol/go-substrate-rpc-client/pkg/gethrpc" 25 "github.com/stafiprotocol/go-substrate-rpc-client/types" 26 ) 27 28 // StorageSubscription is a subscription established through one of the Client's subscribe methods. 29 type StorageSubscription struct { 30 sub *gethrpc.ClientSubscription 31 channel chan types.StorageChangeSet 32 quitOnce sync.Once // ensures quit is closed once 33 } 34 35 // Chan returns the subscription channel. 36 // 37 // The channel is closed when Unsubscribe is called on the subscription. 38 func (s *StorageSubscription) Chan() <-chan types.StorageChangeSet { 39 return s.channel 40 } 41 42 // Err returns the subscription error channel. The intended use of Err is to schedule 43 // resubscription when the client connection is closed unexpectedly. 44 // 45 // The error channel receives a value when the subscription has ended due 46 // to an error. The received error is nil if Close has been called 47 // on the underlying client and no other error has occurred. 48 // 49 // The error channel is closed when Unsubscribe is called on the subscription. 50 func (s *StorageSubscription) Err() <-chan error { 51 return s.sub.Err() 52 } 53 54 // Unsubscribe unsubscribes the notification and closes the error channel. 55 // It can safely be called more than once. 56 func (s *StorageSubscription) Unsubscribe() { 57 s.sub.Unsubscribe() 58 s.quitOnce.Do(func() { 59 close(s.channel) 60 }) 61 } 62 63 // SubscribeStorageRaw subscribes the storage for the given keys, returning a subscription that will 64 // receive server notifications containing the storage change sets. 65 // 66 // Slow subscribers will be dropped eventually. Client buffers up to 20000 notifications before considering the 67 // subscriber dead. The subscription Err channel will receive ErrSubscriptionQueueOverflow. Use a sufficiently 68 // large buffer on the channel or ensure that the channel usually has at least one reader to prevent this issue. 69 func (s *State) SubscribeStorageRaw(keys []types.StorageKey) ( 70 *StorageSubscription, error) { 71 ctx, cancel := context.WithTimeout(context.Background(), config.Default().SubscribeTimeout) 72 defer cancel() 73 74 c := make(chan types.StorageChangeSet) 75 76 keyss := make([]string, len(keys)) 77 for i := range keys { 78 keyss[i] = keys[i].Hex() 79 } 80 81 sub, err := s.client.Subscribe(ctx, "state", "subscribeStorage", "unsubscribeStorage", "storage", c, keyss) 82 if err != nil { 83 return nil, err 84 } 85 86 return &StorageSubscription{sub: sub, channel: c}, nil 87 }