func (c *Lookup) GetConnectionRecordAtState(connectionID, stateID string) (*Record, error) {
	if stateID == "" {
		return nil, errors.New(stateIDEmptyErr)
	}
	var rec Record
	err := getAndUnmarshal(getConnectionStateKeyPrefix()(connectionID, stateID), &rec, c.protocolStateStore)
	if err != nil {
		return nil, fmt.Errorf("faild to get connection record by state : %s, cause : %w", stateID, err)
	}
	return &rec, nil
}
GetConnectionRecordAtState return connection record based on the connection ID and state.
package connection
import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"github.com/hyperledger/aries-framework-go/pkg/common/log"
	"github.com/hyperledger/aries-framework-go/spi/storage"
)
const (
	Namespace          = "didexchange"
	keyPattern         = "%s_%s"
	connIDKeyPrefix    = "conn"
	connStateKeyPrefix = "connstate"
	bothDIDsTagName    = "bothDIDs"
	theirDIDTagName    = "theirDID"
	invKeyPrefix       = "inv"
	eventDataKeyPrefix = "connevent"
	keySeparator       = "_"
	stateIDEmptyErr    = "stateID can't be empty"
)
var logger = log.New("aries-framework/store/connection")
type KeyPrefix func(...string) string
type provider interface {
	ProtocolStateStorageProvider() storage.Provider
	StorageProvider() storage.Provider
}
type Record struct {
	ConnectionID      string
	State             string
	ThreadID          string
	ParentThreadID    string
	TheirLabel        string
	TheirDID          string
	MyDID             string
	ServiceEndPoint   string
	RecipientKeys     []string
	RoutingKeys       []string
	InvitationID      string
	InvitationDID     string
	Implicit          bool
	Namespace         string
	MediaTypeProfiles []string
}
func NewLookup(p provider) (*Lookup, error) {
	store, err := p.StorageProvider().OpenStore(Namespace)
	if err != nil {
		return nil, fmt.Errorf("failed to open permanent store to create new connection recorder: %w", err)
	}
	err = p.StorageProvider().SetStoreConfig(Namespace, storage.StoreConfiguration{TagNames: []string{
		connIDKeyPrefix,
		bothDIDsTagName,
		theirDIDTagName,
	}})
	if err != nil {
		return nil, fmt.Errorf("failed to set store config in permanent store: %w", err)
	}
	protocolStateStore, err := p.ProtocolStateStorageProvider().OpenStore(Namespace)
	if err != nil {
		return nil, fmt.Errorf("failed to open protocol state store to create new connection recorder: %w", err)
	}
	err = p.ProtocolStateStorageProvider().SetStoreConfig(Namespace,
		storage.StoreConfiguration{TagNames: []string{connIDKeyPrefix, connStateKeyPrefix}})
	if err != nil {
		return nil, fmt.Errorf("failed to set store config in protocol state store: %w", err)
	}
	return &Lookup{protocolStateStore: protocolStateStore, store: store}, nil
}
type Lookup struct {
	protocolStateStore storage.Store
	store              storage.Store
}
func (c *Lookup) GetConnectionRecord(connectionID string) (*Record, error) {
	var rec Record
	err := getAndUnmarshal(getConnectionKeyPrefix()(connectionID), &rec, c.store)
	if err != nil {
		if errors.Is(err, storage.ErrDataNotFound) {
			err = getAndUnmarshal(getConnectionKeyPrefix()(connectionID), &rec, c.protocolStateStore)
			if err != nil {
				return nil, err
			}
		} else {
			return nil, err
		}
	}
	return &rec, nil
}
func (c *Lookup) GetConnectionRecordByDIDs(myDID, theirDID string) (*Record, error) {
	return c.queryExpectingOne(bothDIDsTagName+":"+tagValueFromDIDs(myDID, theirDID), c.store)
}
func (c *Lookup) GetConnectionRecordByTheirDID(theirDID string) (*Record, error) {
	return c.queryExpectingOne(theirDIDTagName+":"+tagValueFromDIDs(theirDID), c.store)
}
func (c *Lookup) queryExpectingOne(query string, store storage.Store) (*Record, error) {
	records, err := queryRecordsFromStore(query, store, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get data from persistent store: %w", err)
	}
	if len(records) == 0 {
		return nil, storage.ErrDataNotFound
	}
	logger.Debugf("query '%s' expected 1 result, got %d", query, len(records))
	return records[0], nil
}
func (c *Lookup) QueryConnectionRecords() ([]*Record, error) {
	searchKey := getConnectionKeyPrefix()("")
	var (
		records []*Record
		keys    = make(map[string]struct{})
		err     error
	)
	records, err = queryRecordsFromStore(searchKey, c.store, keys, records)
	if err != nil {
		return nil, fmt.Errorf("failed to get data from persistent store: %w", err)
	}
	records, err = queryRecordsFromStore(searchKey, c.protocolStateStore, keys, records)
	if err != nil {
		return nil, fmt.Errorf("failed to augment records from persistent store with records "+
			"from the protocol state store: %w", err)
	}
	return records, nil
}
func queryRecordsFromStore(searchKey string, store storage.Store, usedKeys map[string]struct{}, appendTo []*Record) (
	[]*Record, error) {
	if usedKeys == nil {
		usedKeys = make(map[string]struct{})
	}
	itr, err := store.Query(searchKey)
	if err != nil {
		return nil, fmt.Errorf("failed to query store: %w", err)
	}
	defer func() {
		errClose := itr.Close()
		if errClose != nil {
			logger.Errorf("failed to close records iterator: %s", errClose.Error())
		}
	}()
	appendTo, err = readRecordIterator(itr, usedKeys, appendTo)
	if err != nil {
		return nil, fmt.Errorf("failed to read records: %w", err)
	}
	return appendTo, nil
}