package concurrency

import (
    "time"

    v3 "github.com/coreos/etcd/clientv3"
    "golang.org/x/net/context"
)

const defaultSessionTTL = 60

// Session represents a lease kept alive for the lifetime of a client.
// Fault-tolerant applications may use sessions to reason about liveness.
type Session struct {
    client *v3.Client
    opts   *sessionOptions
    id     v3.LeaseID

    cancel context.CancelFunc
    donec  <-chan struct{}
}

// NewSession gets the leased session for a client.
func NewSession(client *v3.Client, opts ...SessionOption) (*Session, error) {
    ops := &sessionOptions{ttl: defaultSessionTTL, ctx: client.Ctx()}
    for _, opt := range opts {
        opt(ops)
    }

    resp, err := client.Grant(ops.ctx, int64(ops.ttl))
    if err != nil {
        return nil, err
    }
    id := v3.LeaseID(resp.ID)

    ctx, cancel := context.WithCancel(ops.ctx)
    keepAlive, err := client.KeepAlive(ctx, id)
    if err != nil || keepAlive == nil {
        return nil, err
    }

    donec := make(chan struct{})
    s := &Session{client: client, opts: ops, id: id, cancel: cancel, donec: donec}

    // keep the lease alive until client error or cancelled context
    go func() {
        defer close(donec)
        for range keepAlive {
            // eat messages until keep alive channel closes
        }
    }()

    return s, nil
}

// Client is the etcd client that is attached to the session.
func (s *Session) Client() *v3.Client {
    return s.client
}

// Lease is the lease ID for keys bound to the session.
func (s *Session) Lease() v3.LeaseID { return s.id }

// Done returns a channel that closes when the lease is orphaned, expires, or
// is otherwise no longer being refreshed.
func (s *Session) Done() <-chan struct{} { return s.donec }

// Orphan ends the refresh for the session lease. This is useful
// in case the state of the client connection is indeterminate (revoke
// would fail) or when transferring lease ownership.
func (s *Session) Orphan() {
    s.cancel()
    <-s.donec
}

// Close orphans the session and revokes the session lease.
func (s *Session) Close() error {
    s.Orphan()
    // if revoke takes longer than the ttl, lease is expired anyway
    ctx, cancel := context.WithTimeout(s.opts.ctx, time.Duration(s.opts.ttl)*time.Second)
    _, err := s.client.Revoke(ctx, s.id)
    cancel()
    return err
}

type sessionOptions struct {
    ttl int
    ctx context.Context
}

// SessionOption configures Session.
type SessionOption func(*sessionOptions)

// WithTTL configures the session's TTL in seconds.
// If TTL is <= 0, the default 60 seconds TTL will be used.
func WithTTL(ttl int) SessionOption {
    return func(so *sessionOptions) {
        if ttl > 0 {
            so.ttl = ttl
        }
    }
}

// WithContext assigns a context to the session instead of defaulting to
// using the client context. This is useful for canceling NewSession and
// Close operations immediately without having to close the client. If the
// context is canceled before Close() completes, the session's lease will be
// abandoned and left to expire instead of being revoked.
func WithContext(ctx context.Context) SessionOption {
    return func(so *sessionOptions) {
        so.ctx = ctx
    }
}

session.go的更多相关文章

  1. session实现购物车

    为实现简单的购物功能(购物车添加.账户查看.购物车商品删除.实时的购物商品数量及价格的计算显示.购物车商品数量可手动输入等),用session实现了一简单的以php语言为基础.连接MySQL数据库的购 ...

  2. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  3. 懒加载session 无法打开 no session or session was closed 解决办法(完美解决)

           首先说明一下,hibernate的延迟加载特性(lazy).所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作.因为hibernate当中支持实体对象,外键会与实体对象关联起来.如 ...

  4. 探索ASP.NET MVC5系列之~~~6.Session篇(进程外Session)

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  5. Nhibernate的Session管理

    参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...

  6. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  7. zookeeper源码分析之六session机制

    zookeeper中session意味着一个物理连接,客户端连接服务器成功之后,会发送一个连接型请求,此时就会有session 产生. session由sessionTracker产生的,sessio ...

  8. [转载]Cookie/Session的机制与安全

    Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道.本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题. 因 ...

  9. 修改session垃圾回收几率

    <?php //修改session垃圾回收几率 ini_set('session.gc_probability','1'); ini_set('session.gc_divisor','2'); ...

  10. Nginx反向代理,负载均衡,redis session共享,keepalived高可用

    相关知识自行搜索,直接上干货... 使用的资源: nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换. tomcat服务器两台,由nginx进行反向代理和负载均衡,此 ...

随机推荐

  1. 新手入门vue 使用vue-cli创建项目

    本文是针对对于完全没有了解过vue 和npm,连运行环境和项目构建的都不会的小白,对于前端老司机的就不用看了,浪费时间. 使用npm 与vue-cli 构建vue 项目 第一步:安装运行环境(node ...

  2. JAVA设计模式--学习总结(序)

    设计模式(Design pattern)是一套被反复使用的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 常见的设计模式有23种.分为三大类:创建型模式, ...

  3. 说说Android的MVP模式

    http://toughcoder.NET/blog/2015/11/29/understanding-Android-mvp-pattern/ 安卓应用开发是一个看似容易,实则很难的一门苦活儿.上手 ...

  4. 基类包括字段“ScriptManager1”,但其类型(System.Web.UI.ScriptManager)与控件(System.Web.UI.ScriptManager)的类型不兼容

    首先说下原先的情况,就是原本老项目的Web解决方案是使用.net framework 2.0的老版本, 所以机器也安装过Microsoft ASP.NET 2.0 AJAX Extensions..A ...

  5. springAOP之代理

    AOP是指面向切面编程. 在学习AOP之前先来了解一下代理,因为传说中的AOP其实也对代理的一种应用. 首先来看这样一段代码: public interface Hello { void say(St ...

  6. linux环境安装svn并进行多个源码库区分管理

    关于svn的文档有很多大部分已Windows为例子,因公司没有Windows服务器经过一天的曲折终于初步安装了解了svn.下面一些经验希望能帮助新手 本文采用的yum安装(简单快速没必要源码) 1.y ...

  7. DevOps之四 Jenkins的安装与配置

    CentOS 上 Jenkins 安装 一.添加yum repos,然后安装 sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins ...

  8. Hive中Join的原理和机制

    转自:http://lxw1234.com/archives/2015/06/313.htm 笼统的说,Hive中的Join可分为Common Join(Reduce阶段完成join)和Map Joi ...

  9. CDH简易离线部署文档

        CDH 离线简易部署文档       文档说明 本文为开发部署文档,生产环境需做相应调整. 以下操作尽量在root用户下操作,避免权限问题. 目录 文档说明 2 文档修改历史记录 2 目录 3 ...

  10. Python《学习手册:第二章-习题》

    什么是Python解释器? Python解释器是运行Python程序的程序. 什么是源代码? 源代码是为程序所写的语句:它包括文本文件(通常以.py为文件名结尾)的文件. 什么是字节码? 字节码是Py ...