• 可以看一下 ProxySQL 它能满足你提到的这些需求: https://github.com/sysown/proxysql

    另外一个是 Vitess 但我对它不熟,听 Github 的人说他们在评估这个,你也可以看一下: https://github.com/vitessio/vitess

  • ActiveJob 目的是为了并发/异步执行,改成长度为1的队列,未免削足适履,更合适的解决方案是用 flock,用 Exclusive lock 和 None blocking 来保证一个文件只能被一个 JobWorker 处理,同时也有并发处理多文件的能力

    f = File.open(...)
    if f.flock(File::LOCK_EX | File::LOCK_NB)
      ...
    end
    
  • 直觉是不可能,在我自己机器上跑了一下,结果是相反的,你的ruby是什么版本?

    2.3.2 :018 > Benchmark.measure { maxa(1000)}
     => #<Benchmark::Tms:0x007fcd7a884b78 @label="", @real=3.692405005916953, @cstime=0.0, @cutime=0.0, @stime=0.040000000000000036, @utime=3.6, @total=3.64> 
    2.3.2 :019 > Benchmark.measure { maxf(1000)}
     => #<Benchmark::Tms:0x007fcd7b027b00 @label="", @real=0.8660073862411082, @cstime=0.0, @cutime=0.0, @stime=0.009999999999999898, @utime=0.8300000000000001, @total=0.84> 
    

    好像在2.4测试就反过来了,是因为2.4的那个Array#max实现更新吗,等下再看看...

  • 推模式问题在于任何影响订阅关系的行为,比如屏蔽或者取消屏蔽,还需要对已经推送的event进行修改

  • 和推不一样的,推的模式在产生event的时候,需要写入大量数据,而且这种设计也没有 屏蔽/取消屏蔽 导致数据不正确的问题

  • 我觉得拉的模式缺点讲得不正确,把event和friendship强关联的设计是这个造成这个缺点的主要原因,而不是拉模式本身的问题。

    正确设计应该有一个中间表,比如 event_subscribers ,表结构是这样的:

    user_id, subscribed_user_id
    3      , 4
    3      , 8
    1      , 4
    1      , 10
    

    SQL查询是固定的:

    select events.* from events, event_subscribers
        where events.user_id = event_subscribers.subscribed_user_id and event_subscribers.user_id = 3
    

    所有的屏蔽,过滤都是对event_subscribers这个中间表数据做操作

  • 可以先用数组的前一个元素做group_by,然后用map!方法将后一个元素做replace:

    data = [['A', '123'], ['A', '1223'], ['A', '12343'], ['A', '122XX33'], ['B', '678'], ['B', '612378'], ['B', '67XX8'], ['C', '100'], ['C', '1000']]
    
    data.group_by(&:first).each{|_, v| v.map!(&:last)}
    
    # => {"A"=>["123", "1223", "12343", "122XX33"], "B"=>["678", "612378", "67XX8"], "C"=>["100", "1000"]} 
    
  • 除了添加额外字段对比session之外,你也可以用一样的思路依赖devise内置的model Trackable(通常我都会建议在使用devise的项目中设置这个模块)的字段sign_in_count,然后写一个hook,几行代码就可以满足你的需求:

    Warden::Manager. after_authentication do |record, warden, options|
      warden.session(options[:scope])[:sign_in_count] = record.sign_in_count
    end
    
    Warden::Manager.after_fetch do |record, warden, options|
      if record.sign_in_count != warden.session(options[:scope])[:sign_in_count]
        warden.logout(options[:scope])
        throw :warden, :scope => options[:scope], :message => "Signin from another IP address #{record.last_sign_in_ip}"
      end
    end
    

    基本上做devise的扩展都是通过hook来进行,非常简洁方便。

  • 想了一个无需默认0 Hash的一行版:

    a.inject({}){|m, (k, v)| m.merge(k => v.to_i) {|k, old, new| old + new} }
    

Ruby程序猿,写OC的果黑程序猿,蝉游记2号保管猿