• 之前用了 OpenResty,接收所有域名指向到默认 Rails 应用(没有做数据隔离),配置自动获取 Let's Encrypt 就可用。

    每一个客户有需要自己域名 cname 过来即可。

    问题是有大量莫名的乱七八糟的域名解析过来,导致大量无效的证书获取触发 Let's encrypt 的 limit 限制。

    还在找更好的方案

  • 再见啦,Ruby on Rails at September 10, 2023

    提另外一个担心又欣慰的事,在大家喊引入静态类型的时候,matz 坚持不在 Ruby 中引入类型,坚持把 type 隔离在外部库来支持。

  • linux, vim, rvm, firefox, 就这么多,本机开发调试。

    pg/redis/elastic_search/qdrant/Rabbit MQ/Kafka等各种配套服务可以考虑docker直接起服务; 一般超稳定的软件比如 pg 我会本机直接安装,各种不确定的用 docker。

  • 都 NLUI 了,前后端分离是啥

  • 勿执勿念,放弃放下。

  • 我可以比年轻人拿得少一点(不止一点),

    摆正心态,打工挣钱,难受都是自己为难自己。

  • 国内 Ruby 圈子真的很小 at April 18, 2023

    那就是我没用好(悲伤)

  • 一个奇葩的问题 at April 18, 2023

    这是直接用 sidekiq(include Sidekiq::Job)会发生的问题,

    还是基于 ActiveJob 使用也会发生的问题?

  • 第一次看到这么惊喜的年龄要求

  • 把它设计成 resource,then restful

  • 管理层也只是一个工作,没什么不一样。

  • 遵守,挺好的。

  • ChatClient 就是一个 Faraday.new,太简单了所以没贴。细节在这里: https://github.com/as181920/openai_api_proxy/blob/main/lib/openai_api_proxy/chat_client.rb

  • 前些天在老产品上面也添加了一个给老用户体验的, https://www.vcooline.com

    主要加了返回 stream 的处理(一个字一个字蹦出来)

    def perform_openai_request(prompt:)
      completion_content = ""
      start_chunk_message
      OpenaiApiProxy::ChatClient.new(api_key: ‘’, organization_id: ‘’).create(
        model: "gpt-3.5-turbo",
        messages: generate_chat_messages(prompt),
        max_tokens:1234
        user: user.to_gid.to_s,
        stream: true
      ) do |reqt|
        reqt.options.on_data = Proc.new do |chunk, overall_received_bytes, env|
          chunk_contents = handle_openai_chunk_data(chunk, overall_received_bytes, env)
          chunk_contents.compact_blank.map { |chunk_content| completion_content.concat(chunk_content) }
        end 
      end 
    
      completion_content.presence
        &.tap { |content| decrease_usage_quota(content:) }
        &.tap { |content| save_bot_message(content:) }
    rescue OpenaiApiProxy::Client::ServerError, OpenaiApiProxy::Client::InternalError => e
      Rails.logger.error "#{self.class.name} perform #{e.class.name}: #{e.message}"
      send_chunk_message(content: "系统繁忙,请稍候再试。")
    end 
    
    def handle_openai_chunk_data(chunk, _overall_received_bytes, _env)
      chunk.force_encoding("UTF-8").encode("UTF-8", invalid: :replace, undef: :replace, replace: "") 
        .split("\n\n")
        .map { |line| line.sub(/^data:\ */, "") }
        .compact_blank
        .map.each_with_object([]) do |chunk_line, chunk_contents|
          break chunk_contents if chunk_line == "[DONE]"
    
          chunk_info = JSON.parse chunk_line
          # start_chunk_message if chunk_info.dig("choices", 0, "delta", "role").eql?("assistant")
          chunk_info.dig("choices", 0, "delta", "content").presence
            &.tap { |chunk_content| chunk_contents.push(chunk_content) }
            &.tap { |chunk_content| send_chunk_message(content: chunk_content) }
        end 
    end 
    
    def send_chunk_message(content:)
      start_chunk_input
      message.broadcast_append_to \
        ActionView::RecordIdentifier.dom_id(message.conversation, :namespace_example),
        target: reply_message_dom_id,
        html: content
    end 
    
    
  • 效率真厉害👍

  • http.get(api).body.dig "choices", 0, "text" 是不是大概就这么一行的事情

  • 也不是一定要购买云服务,一些基础的软件 redis/pg/mq 等自建还是蛮稳定的,看业务要求到什么程度。

  • Ruby 工具书

    Rails Guide(类似于本科学经济学原理,研究生学经济学原理,博士还是学经济学原理)

    源码不着急

  • 如果有 turbo 但没有 stimulus 的情况,可以考虑

    document.addEventListener("turbo:load", function() 
    document.addEventListener("turbo:frame-load", function(ev)
    

    来做初始化

  • Rails 应用的部署管理 at August 13, 2022

    这边一直是这么干的,所有部署全部是 production env。走 cap 的 linked_file 文件(并转化成 ENV 参数),来区分不同环境需要的不同配置。

     class Application < Rails::Application
        config.before_configuration do
            env_file = Rails.root.join("config/local_env.yml")
            YAML.load_file(env_file, aliases: true)[Rails.env].to_h.each do |key, value|
              ENV[key.to_s] = value.to_s
            end if File.file?(env_file)
          end 
    end
    
  • 关于聚合支付 at March 23, 2022

    这是汇付天下的产品吧,我去了解了解

  • 关于聚合支付 at March 22, 2022

    最近遇到分账需求,调研了一下费用普遍过高,不适合中小商家使用,目前考虑单独对接微信&支付宝。

    在这两大平台提供原生分账能力的情况下,不清楚现在聚合支付机构收取那么高的年费是基于什么缘故(涉及分账就贵,牌照虽然贵,另外没牌照走银行托管账户方案的也贵)。

  • / fix disable_with on link and submit inside turbo-frame
    Rails.delegate(document, Rails.linkDisableSelector,   "turbo:before-cache", Rails.enableElement)
    Rails.delegate(document, Rails.buttonDisableSelector, "turbo:before-cache", Rails.enableElement)
    Rails.delegate(document, Rails.buttonDisableSelector, "turbo:submit-end", Rails.enableElement)
    Rails.delegate(document, Rails.formSubmitSelector, "turbo:submit-start", Rails.disableElement)
    Rails.delegate(document, Rails.formSubmitSelector, "turbo:submit-end", Rails.enableElement)
    Rails.delegate(document, Rails.formSubmitSelector, "turbo:before-cache", Rails.enableElement)
    
    
  • 按时间顺序,foreman 确实在 systemd 成熟之前,(那时候生产很多用 monit,sidekiq 还是自带 daemon,终于等到 systemd 成熟 sidekiq 等库在新版设计时候也去掉了自身的 daemon 机制,推荐用系统自带的机制);

    linux 从原来的 init 机制,争议 systemd 是否管太多,切换到 systemd,再 systemd 支持 user level unit 等逐渐成熟,这个过程前有很多其它 daemon 方案,现在生产用 systemd 应该比较成熟了 (用容器是另一套方案)

    foreman 方便本地开发(我本地会用),方便一键启关联服务,避免多终端看日志不方便等,好像 rails 7 默认的./bin/dev 执行的就是 forman start

  • 干后端,兼上运维,兼上前端,略搞产品设计,完了找人指点建议,人说该补上销售技能。

  • 没意外事项就过来

  • 刚手动调试,监听 scroll 判断后,js 主动把下一个 turbo_frame 的 loading 设置为 eager 是可行的(再下一个依旧是 lazy load,同样逻辑页面到一定位置后修改为 eager)。

  • 使用 Let's encrypt 及子域名泛解析的话,要自动更新证书需要联动 dns 解析 api 才能完成验证吧

  • 官方产品接口有些还停留在 V2,包括企业支付。 https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml

  • 自己写(了个 engine),抄袭了相关 gem 的加解密