用的什么技术栈?ActionCable?IM 框架?
已经分布式锁了就不需要叠加 synchronized 了吧。 不同分布式锁实现的超时处理机制不一样。 gem 的话,redis 的 redlock,pg 的 with_advisory_lock,都可以拿来就用。
之前用了 OpenResty,接收所有域名指向到默认 Rails 应用(没有做数据隔离),配置自动获取 Let's Encrypt 就可用。
每一个客户有需要自己域名 cname 过来即可。
问题是有大量莫名的乱七八糟的域名解析过来,导致大量无效的证书获取触发 Let's encrypt 的 limit 限制。
还在找更好的方案
提另外一个担心又欣慰的事,在大家喊引入静态类型的时候,matz 坚持不在 Ruby 中引入类型,坚持把 type 隔离在外部库来支持。
linux, vim, rvm, firefox, 就这么多,本机开发调试。
pg/redis/elastic_search/qdrant/Rabbit MQ/Kafka等各种配套服务可以考虑docker直接起服务; 一般超稳定的软件比如 pg 我会本机直接安装,各种不确定的用 docker。
都 NLUI 了,前后端分离是啥
勿执勿念,放弃放下。
我可以比年轻人拿得少一点(不止一点),
摆正心态,打工挣钱,难受都是自己为难自己。
那就是我没用好(悲伤)
这是直接用 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)
来做初始化
这边一直是这么干的,所有部署全部是 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
这是汇付天下的产品吧,我去了解了解
最近遇到分账需求,调研了一下费用普遍过高,不适合中小商家使用,目前考虑单独对接微信&支付宝。
在这两大平台提供原生分账能力的情况下,不清楚现在聚合支付机构收取那么高的年费是基于什么缘故(涉及分账就贵,牌照虽然贵,另外没牌照走银行托管账户方案的也贵)。
/ 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 才能完成验证吧