Commit 0f982532 by liangyuzhe

推送服务代码重构

parent d2b2b524
......@@ -7,7 +7,8 @@ ruby '2.6.0'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.2', '>= 5.2.2.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# gem 'sqlite3'
gem 'mysql2'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
......
......@@ -133,6 +133,7 @@ GEM
minitest (5.11.3)
msgpack (1.2.10)
multi_xml (0.6.0)
mysql2 (0.5.2)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (5.1.0)
......@@ -228,7 +229,6 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.4.1)
sshkit (1.18.0)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
......@@ -272,6 +272,7 @@ DEPENDENCIES
igetui-ruby
jbuilder (~> 2.5)
listen (>= 3.0.5, < 3.2)
mysql2
puma (~> 3.11)
rails (~> 5.2.2, >= 5.2.2.1)
rails_param (~> 0.10.2)
......@@ -282,7 +283,6 @@ DEPENDENCIES
sidekiq (~> 4.1, >= 4.1.2)
spring
spring-watcher-listen (~> 2.0.0)
sqlite3
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
......
......@@ -21,29 +21,21 @@ class PushsController < ApplicationController
# igetui_opts 个推推送的额外选项
def push
param! :app_name, String, required: true
param! :device_ids_opts, String, required: true
# param! :device_ids_opts, String, required: true
param! :message, String, required: true
param! :igetui_opts, String
param! :app_type, String
param! :sync_push, String
param! :user_ids, Array, required: true
igetui_opts = JSON.parse(params[:igetui_opts]) rescue {}
message = JSON.parse(params[:message]) rescue {}
device_ids_opts = JSON.parse(params[:device_ids_opts]) rescue {}
user_ids = JSON.parse(params[:user_ids]) rescue {}
token = token_and_options(request).first
if token == Token.token(params[:app_name])
if params.has_key?(:sync_push)
timeout_seconds = $redis.get('push_timeout').to_i
if timeout_seconds > 0
Timeout.timeout(timeout_seconds) {
::PushWorker.new.perform(device_ids_opts, message, igetui_opts, params[:app_type])
}
else
::PushWorker.new.perform(device_ids_opts, message, igetui_opts, params[:app_type])
end
else
::PushWorker.perform_async(device_ids_opts, message, igetui_opts, params[:app_type])
end
push_client = PushSyncClient.new({sync_push: params[:sync_push], user_ids: user_ids, message: message, igetui_opts: igetui_opts})
push_client.do_push
render json: { code: 0, message: 'success', describe: '异步任务正在处理'}
else
render json: { code: -1, message: 'token 错误/过期'}
......
class UserDevice < ApplicationRecord
# 当前app端传递的platform的值:
# android: igetui, xiaomi, huawei
# iso: igetui 目前还不清楚为啥不用apns,暂时不修改
enum platform: %i[igetui apns xiaomi huawei]
enum device_platform: %i[ios android]
# 用于区分当前的应用,为了推送准备, 因为推送需要根据不同的应用使用不同的 id,secret等。
enum app_type: %i[ik_duli lx_duli lx_yun]
end
\ No newline at end of file
#有关于底层sdk的数据交互封装,消息推送
module Push
module Igetui
module Base
def push_message_to(pusher, pusher_type, template_type, template_data, client_id)
client_id_list = Array(client_id)
case pusher_type
when 'push_message_to_single'
message = IGeTui::SingleMessage.new
message.data = set_template_data(template_type, template_data)
client_id_list.map do |client_id|
client = IGeTui::Client.new(client_id)
pusher.push_message_to_single(message, client)
end
when 'push_message_to_list'
message = IGeTui::ListMessage.new
message.data = set_template_data(template_type, template_data)
content_id = pusher.get_content_id(message)
clients = client_id_list.map { |client_id| IGeTui::Client.new(client_id) }
pusher.push_message_to_list(content_id, clients)
when 'push_message_to_app'
message = IGeTui::AppMessage.new
message.data = set_template_data(template_type, template_data)
message.app_id_list = client_id_list
pusher.push_message_to_app(message)
end
end
def set_template_data(template_type, template_data)
@template ||= "IGeTui::#{template_type}".constantize.new
case template_type
when 'NotificationTemplate', 'NotyPopLoadTemplate', 'LinkTemplate'
template_data.reverse_merge!(Settings.platform_settings.igetui['template_base'])
template_data.each do |k, v|
@template.send("#{k}=", v)
end
@template.set_push_info(*template_data[:push_info]) if template_data.key? :push_info
when 'TransmissionTemplate'
@template.transmission_content = template_data[:transmission_content].is_a?(Hash) ? template_data[:transmission_content].to_json : template_data[:transmission_content]
@template.transmission_type = template_data[:transmission_type] if template_data.key?(:transmission_type)
@template.set_push_info(*template_data[:push_info]) if template_data.key? :push_info
end
end
end
end
end
\ No newline at end of file
module Push
module Igetui
module List
def data_hash(user_device_ids, template_data = {}, igetui_opts = {})
# 包装成igetui 真正需要的参数格式
igetui_opts = HashWithIndifferentAccess.new(igetui_opts)
igetui_opts[:transmission_content] = template_data
if user_device_ids.size > 1
transmission_to_list_igetui(igetui_opts)
else
transmission_to_igetui(igetui_opts)
end
rescue StandardError => err
::Push::Log.error(err)
end
def config
{
push_type: 2
}
end
def transmission_to_igetui(template_data = {})
template_data = handle_template_data(template_data)
{template_data: template_data, template_type: 'TransmissionTemplate'}
end
def transmission_to_list_igetui(template_data = {})
template_data = handle_template_data(template_data)
{template_data: template_data, template_type: 'TransmissionTemplate', pusher_type: 'push_message_to_list'}
end
private
def handle_template_data(template_data)
template_data = HashWithIndifferentAccess.new(template_data)
transmission_content = HashWithIndifferentAccess.new(template_data.delete(:transmission_content))
transmission_content[:push_type] ||= config[:push_type]
template_data[:transmission_type] ||= 0
template_data[:transmission_content] = transmission_content.as_json
template_data
end
end
end
end
\ No newline at end of file
module Push
class IgetuiAndroid
include Push::Igetui::Base
include Push::Igetui::List
PUSHERTYPES = %w[push_message_to_single push_message_to_list push_message_to_app].freeze
TEMPLATETYPES = %w[LinkTemplate NotificationTemplate TransmissionTemplate NotyPopLoadTemplate].freeze
def initialize(user_device_ids, opts)
opts = HashWithIndifferentAccess.new(opts)
@template_data = opts[:template_data]
@igetui_opts = opts[:igetui_opts]
@user_device_ids = user_device_ids
end
def push
data_hash_opts = data_hash(@user_device_ids, @template_data, @igetui_opts)
pusher_type = PUSHERTYPES.include?((data_hash_opts[:pusher_type]).to_s) ? data_hash_opts[:pusher_type] : 'push_message_to_single'
template_type = TEMPLATETYPES.include?((data_hash_opts[:template_type]).to_s) ? data_hash_opts[:template_type] : 'NotificationTemplate'
template_data = data_hash_opts[:template_data]
result = push_message_to(pusher, pusher_type, template_type, template_data, @user_device_ids)
::Push::Log.info("igetui_push: \n template_data: #{template_data}\n user_device_ids: #{@user_device_ids}\n response: #{result}")
end
private
def pusher
@pusher ||=
IGeTui.pusher(
Settings.platform_settings.igetui.android['app_id'],
Settings.platform_settings.igetui.android['app_key'],
Settings.platform_settings.igetui.android['master_secret']
)
end
end
end
module Push
class IgetuiIos
include Push::Igetui::Base
include Push::Igetui::List
PUSHERTYPES = %w[push_message_to_single push_message_to_list push_message_to_app].freeze
TEMPLATETYPES = %w[LinkTemplate NotificationTemplate TransmissionTemplate NotyPopLoadTemplate].freeze
def initialize(user_device_ids, opts)
opts = HashWithIndifferentAccess.new(opts)
@template_data = opts[:template_data]
@igetui_opts = opts[:igetui_opts]
@user_device_ids = user_device_ids
end
def push
data_hash_opts = data_hash(@user_device_ids, @template_data, @igetui_opts)
pusher_type = PUSHERTYPES.include?((data_hash_opts[:pusher_type]).to_s) ? data_hash_opts[:pusher_type] : 'push_message_to_single'
template_type = TEMPLATETYPES.include?((data_hash_opts[:template_type]).to_s) ? data_hash_opts[:template_type] : 'NotificationTemplate'
template_data = data_hash_opts[:template_data]
result = push_message_to(pusher, pusher_type, template_type, template_data, @user_device_ids)
::Push::Log.info("igetui_push: \n template_data: #{template_data}\n user_device_ids: #{@user_device_ids}\n response: #{result}")
end
private
def pusher
@pusher ||=
IGeTui.pusher(
Settings.platform_settings.igetui.ios['app_id'],
Settings.platform_settings.igetui.ios['app_key'],
Settings.platform_settings.igetui.ios['master_secret']
)
end
end
end
#push功能的代理选择是否为异步推送
class PushSyncClient
def initialize(opts={})
opts = HashWithIndifferentAccess.new(opts)
@sync_push = opts[:sync_push]
@opts = opts
end
def do_push
push_sync?
end
def push_sync?
if @sync_push
timeout_seconds = $redis.get('push_timeout').to_i
if timeout_seconds > 0
Timeout.timeout(timeout_seconds) {
::PushWorker.new.perform(@opts)
}
else
::PushWorker.new.perform(@opts)
end
else
::PushWorker.perform_async(@opts)
end
end
end
\ No newline at end of file
#push功能的代理选择用哪种推送工具1.个推 2.小米 3.华为
class PushToolClient
def initialize(opts={})
@user_ids = opts[:user_ids]
@opts = opts
end
def do_push
@push_collections ||= push_collections
Push::IgetuiIos.push(@push_collections[:igetui_ios], @opts) if @push_collections[:igetui_ios].present?
Push::IgetuiAndroid.push(@push_collections[:igetui_android], @opts) if @push_collections[:igetui_android].present?
#现在好像不用了
# Push::IgetuiIos.push(@push_collections[:igetui_ios], @opts) if @push_collections[:apns].present?
# Push::IgetuiAndroid.push(@push_collections[:igetui_android], @opts) if @push_collections[:apns].present?
Push::Xiaomi.push(@push_collections[:xiaomi], @opts[:message]) if @push_collections[:xiaomi].present?
Push::Huawei.push(@push_collections[:huawei], @opts[:message]) if @push_collections[:huawei].present?
end
private
def push_collections
@push_collection = {
igetui_ios: [],
igetui_android: [],
apns: [],
xiaomi: [],
huawei: []
}
user_devices = UserDevice.where(user_id: @user_ids)
user_devices.each do |user_device|
client_id = user_device.client_id
case user_device.platform
when 'igetui'
if user_device.device_platform == 'ios'
@push_collection[:igetui_ios] << client_id
else
@push_collection[:igetui_ios] << client_id
end
when 'apns'
@push_collection[:apns] << client_id
when 'xiaomi'
@push_collection[:xiaomi] << client_id
when 'huawei'
@push_collection[:huawei] << client_id
end
end
end
end
\ No newline at end of file
......@@ -2,8 +2,9 @@ class PushWorker
include Sidekiq::Worker
sidekiq_options queue: :push
def perform(device_ids_opts, message, igetui_opts, platform = nil)
Push.push(device_ids_opts, message, igetui_opts, platform)
def perform(opts)
::PushToolClient.do_push(opts)
# Push.push(user_ids, message, igetui_opts, platform)
rescue StandardError => e
ErrorLog.error(e)
end
......
......@@ -5,13 +5,17 @@
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
adapter: mysql2
encoding: utf8
host: rm-m5ef10gzq1n5e7b9abo.mysql.rds.aliyuncs.com
username: crm_rw
password: pHB+!*Uv9Rl9
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
database: crm_dev
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
......
default: &default
adapter: mysql2
encoding: utf8
host: rm-m5ef10gzq1n5e7b9abo.mysql.rds.aliyuncs.com
username: crm_rw
password: pHB+!*Uv9Rl9
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: crm_dev
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment