func Lock(ctx context.Context, store *coal.Store, value Value, timeout time.Duration) (bool, error) {
	ctx, span := xo.Trace(ctx, "glut/Lock")
	span.Tag("timeout", timeout.String())
	defer span.End()
	meta := GetMeta(value)
	base := value.GetBase()
	key, err := GetKey(value)
	if err != nil {
		return false, err
	}
	if base.Token.IsZero() {
		base.Token = coal.New()
	}
	span.Tag("key", key)
	span.Tag("ttl", meta.TTL.String())
	span.Tag("token", base.Token.Hex())
	if timeout == 0 {
		return false, xo.F("missing timeout")
	}
	if meta.TTL > 0 && meta.TTL < timeout {
		return false, xo.F("timeout greater than time to live")
	}
	var deadline *time.Time
	if meta.TTL > 0 {
		deadline = coal.T(time.Now().Add(meta.TTL))
	}
	locked := time.Now().Add(timeout)
	model := Model{
		Key:      key,
		Data:     nil,
		Deadline: deadline,
		Locked:   &locked,
		Token:    coal.P(base.Token),
	}
	inserted, err := store.M(&Model{}).InsertIfMissing(ctx, bson.M{
		"Key": key,
	}, &model, false)
	if err != nil {
		return false, err
	}
	if inserted {
		return true, nil
	}
	found, err := store.M(&Model{}).UpdateFirst(ctx, &model, bson.M{
		"$and": []bson.M{
			{
				"Key": key,
			},
			{
				"$or": []bson.M{
					{
						"Token": nil,
					},
					{
						"Locked": bson.M{
							"$lt": time.Now(),
						},
					},
					{
						"Token": base.Token,
					},
				},
			},
		},
	}, bson.M{
		"$set": bson.M{
			"Deadline": deadline,
			"Locked":   locked,
			"Token":    base.Token,
		},
	}, nil, false)
	if err != nil {
		return false, err
	}
	err = model.Data.Unmarshal(value, meta.Coding)
	if err != nil {
		return false, err
	}
	err = value.Validate()
	if err != nil {
		return false, err
	}
	return found, nil
}
Lock will lock and read the specified value. Lock may create a new value in
the process and lock it right away. It will also update the deadline of the
value if a time to live is set.
package glut
import (
	"context"
	"time"
	"github.com/256dpi/xo"
	"go.mongodb.org/mongo-driver/bson"
	"github.com/256dpi/fire/coal"
	"github.com/256dpi/fire/stick"
)