func (s *stm) fetchTTL(iface STM, key string) (int64, error) {
	// check wset cache
	if wv, ok := s.wset[key]; ok {
		return wv.ttl, nil
	}

	// Read ttl through s.ttlset cache
	if ttl, ok := s.ttlset[key]; ok {
		return ttl, nil
	}

	// Read kv and lease ID, and cache new TTL
	getResp := iface.fetch(key) // call correct implementation of fetch()
	if len(getResp.Kvs) == 0 {
		return 0, ErrNotFound{Key: key}
	}
	leaseID := v3.LeaseID(getResp.Kvs[0].Lease)
	if leaseID == 0 {
		s.ttlset[key] = 0 // 0 is default value, but now 'ok' will be true on check
		return 0, nil
	}
	span, ctx := tracing.AddSpanToAnyExisting(s.ctx, "etcd.TimeToLive")
	defer tracing.FinishAnySpan(span)
	leaseResp, err := s.client.TimeToLive(ctx, leaseID)
	if err != nil {
		panic(stmError{err})
	}
	s.ttlset[key] = leaseResp.TTL
	for _, key := range leaseResp.Keys {
		s.ttlset[string(key)] = leaseResp.TTL
	}
	return leaseResp.TTL, nil
}
func (s *stm) fetchTTL(iface STM, key string) (int64, error) {
	
	if wv, ok := s.wset[key]; ok {
		return wv.ttl, nil
	}

	
	if ttl, ok := s.ttlset[key]; ok {
		return ttl, nil
	}

	
	getResp := iface.fetch(key) 
	if len(getResp.Kvs) == 0 {
		return 0, ErrNotFound{Key: key}
	}
	leaseID := v3.LeaseID(getResp.Kvs[0].Lease)
	if leaseID == 0 {
		s.ttlset[key] = 0 
		return 0, nil
	}
	span, ctx := tracing.AddSpanToAnyExisting(s.ctx, "etcd.TimeToLive")
	defer tracing.FinishAnySpan(span)
	leaseResp, err := s.client.TimeToLive(ctx, leaseID)
	if err != nil {
		panic(stmError{err})
	}
	s.ttlset[key] = leaseResp.TTL
	for _, key := range leaseResp.Keys {
		s.ttlset[string(key)] = leaseResp.TTL
	}
	return leaseResp.TTL, nil
}
func ( s * stm ) fetchTTL ( iface STM , key string ) ( int64 , error ) { // check wset cache if wv , ok := s . wset [ key ] ; ok { return wv . ttl , nil } // Read ttl through s.ttlset cache if ttl , ok := s . ttlset [ key ] ; ok { return ttl , nil } // Read kv and lease ID, and cache new TTL getResp := iface . fetch ( key ) // call correct implementation of fetch() if len ( getResp . Kvs ) == 0 { return 0 , ErrNotFound { Key : key } } leaseID := v3 . LeaseID ( getResp . Kvs [ 0 ] . Lease ) if leaseID == 0 { s . ttlset [ key ] = 0 // 0 is default value, but now 'ok' will be true on check return 0 , nil } span , ctx := tracing . AddSpanToAnyExisting ( s . ctx , " " ) defer tracing . FinishAnySpan ( span ) leaseResp , err := s . client . TimeToLive ( ctx , leaseID ) if err != nil { panic ( stmError { err } ) } s . ttlset [ key ] = leaseResp . TTL for _ , key := range leaseResp . Keys { s . ttlset [ string ( key ) ] = leaseResp . TTL } return leaseResp . TTL , nil }
// fetchTTL contains the essential implementation of TTL().
//
// Note that 'iface' should either be the receiver 's' or a containing
// 'stmSerializeable'--the only reason 'iface' is passed as a separate argument
// is because fetchTTL calls iface.fetch(), and the implementation of 'fetch' is
// different for stm and stmSerializeable. Passing the interface ensures the
// correct version of fetch() is called
fetchTTL contains the essential implementation of TTL () . Note that iface should either be the receiver s or a containing stmSerializeable -- the only reason iface is passed as a separate argument is because fetchTTL calls iface . fetch () and the implementation of fetch is different for stm and stmSerializeable . Passing the interface ensures the correct version of fetch () is called