func (c *Core) stopExpiration() error {
	if c.expiration != nil {
		if err := c.expiration.Stop(); err != nil {
			return err
		}
		c.metricsMutex.Lock()
		defer c.metricsMutex.Unlock()
		c.expiration = nil
	}
	return nil
}
stopExpiration is used to stop the expiration manager before
sealing the Vault.
package vault
import (
	"encoding/json"
	"fmt"
	"path"
	"strings"
	"sync"
	"time"
	"github.com/armon/go-metrics"
	log "github.com/mgutz/logxi/v1"
	"github.com/hashicorp/go-uuid"
	"github.com/hashicorp/vault/helper/jsonutil"
	"github.com/hashicorp/vault/logical"
)
const (
	expirationSubPath = "expire/"
	leaseViewPrefix = "id/"
	tokenViewPrefix = "token/"
	maxRevokeAttempts = 6
	revokeRetryBase = 10 * time.Second
	minRevokeDelay = 5 * time.Second
	maxLeaseTTL = 32 * 24 * time.Hour
	defaultLeaseTTL = maxLeaseTTL
)
type ExpirationManager struct {
	router     *Router
	idView     *BarrierView
	tokenView  *BarrierView
	tokenStore *TokenStore
	logger     log.Logger
	pending     map[string]*time.Timer
	pendingLock sync.Mutex
}
func NewExpirationManager(router *Router, view *BarrierView, ts *TokenStore, logger log.Logger) *ExpirationManager {
	if logger == nil {
		logger = log.New("expiration_manager")
	}
	exp := &ExpirationManager{
		router:     router,
		idView:     view.SubView(leaseViewPrefix),
		tokenView:  view.SubView(tokenViewPrefix),
		tokenStore: ts,
		logger:     logger,
		pending:    make(map[string]*time.Timer),
	}
	return exp
}
func (c *Core) setupExpiration() error {
	c.metricsMutex.Lock()
	defer c.metricsMutex.Unlock()
	view := c.systemBarrierView.SubView(expirationSubPath)
	mgr := NewExpirationManager(c.router, view, c.tokenStore, c.logger)
	c.expiration = mgr
	c.tokenStore.SetExpirationManager(mgr)
	if err := c.expiration.Restore(); err != nil {
		return fmt.Errorf("expiration state restore failed: %v", err)
	}
	return nil
}