jieshun-parking 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e62dbeac0ad063a0b1ccfd6c05f734d9eb029601db476a8902e76f90ccd020b2
4
- data.tar.gz: 4a74322b5e1e9736dd085019b5dc7b5757778d3cc0f4a23b047c4799767c2d45
3
+ metadata.gz: 68926a0aeaf9f28755c8f054a766714f1ebe50919458c8085bc69d09a3b4c150
4
+ data.tar.gz: 1b625c14754f9dd1b34892d0f552412809d1cf4c67859ee24544f8a6269fcd90
5
5
  SHA512:
6
- metadata.gz: 9eea2615ad75a03358adb76f297570df9f5ca3ce04f477ce48119c71fea806b7477123ee5d19b937d3e3af35c6ad3fe09252d3e84c802e451d64d4640aae2f24
7
- data.tar.gz: aee37bc88b551134697e7c8f5575d21c5f8282d0cc9ffe38ed0f461cdcdee735c3f1863ffe4d19d7490cc97c7a0a54c312a7d31cd5cd4c2322f5d7c6ed7d15d0
6
+ metadata.gz: 2b27373583050c8574fbfbf209c03e2f8e44b06f4a65bb56e1873f526e1f8f04c64c3fdae520141654a4062b2b80594f73cdae843ca4d5806513c89e679abae2
7
+ data.tar.gz: 3a1ab8e23b5b34339d65364835cb33872ad3a000156c24e557a85d7bd556dfaa43e87157bda9ff9517b76ca42c6bbc3082db60ba8a5e3e4e509ead55892dcc49
@@ -1,82 +1,106 @@
1
1
  module Jieshun
2
- module Parking
3
- # 捷顺数据中心 Client, 目前主要用来获取图片, 对应文档为 QX205_数据中心标准推送协议-1.1.6(1)
4
- class DataCenterClient
2
+ module Parking
3
+ # 捷顺数据中心 Client, 目前主要用来获取图片, 对应文档为 QX205_数据中心标准推送协议-1.1.6(1)
4
+ class DataCenterClient
5
+ REDIS_AUTH_KEY = 'jieshun.parking.datacenter.auth.token'
6
+ REDIS_AUTH_KEY_LOCK = 'jieshun.parking.datacenter.auth.token.lock'
7
+ MAX_RETRY_COUNT = 3 # 定义refresh_token 最大重试次数
8
+ def initialize(configuration, http_client = StandardHttpClient.new)
9
+ @configuration = configuration
10
+ @http_client = http_client
11
+ @redis_client = RedisClient.new(@configuration.redis_config)
12
+ end
5
13
 
6
- REDIS_AUTH_KEY = 'jieshun.parking.datacenter.auth.token'
14
+ def get_auth_token
15
+ @redis_client.redis_get(REDIS_AUTH_KEY)
16
+ end
7
17
 
8
- def initialize(configuration, http_client = StandardHttpClient.new)
9
- @configuration = configuration
10
- @http_client = http_client
11
- @redis_client = RedisClient.new(@configuration.redis_config)
12
- end
18
+ def login_if_required
19
+ auth_token = get_auth_token
20
+ if Jieshun::Parking.always_login || auth_token.nil? || auth_token.empty?
21
+ # 使用 Redis 锁来避免并发刷新
22
+ lock_key = REDIS_AUTH_KEY_LOCK
23
+ begin
24
+ # 设置一个5秒过期的锁
25
+ if @redis_client.redis_set_nx_lock(lock_key, 5)
26
+ # 重试机制
27
+ Retry.with_retries(max_tries: MAX_RETRY_COUNT, sleep_seconds: 1) do
28
+ # 过程中遇到错误重试时, 检查本地token是否存在
29
+ auth_token = get_auth_token
30
+ if auth_token
31
+ yield(auth_token)
32
+ else
33
+ refresh_token do |auth_token|
34
+ yield(auth_token)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ rescue StandardError => e
40
+ Jieshun::Parking.logger.info("Failed to refresh token;error: #{e.message}")
41
+ ensure
42
+ # 确保锁最终被释放
43
+ @redis_client.redis_del(lock_key)
44
+ end
45
+ else
46
+ yield(auth_token)
47
+ end
48
+ end
13
49
 
14
- def get_auth_token
15
- @redis_client.redis_get(REDIS_AUTH_KEY)
16
- end
50
+ def refresh_token
51
+ hash = { pno: @configuration.pno, secret: @configuration.secret }
52
+ @http_client.post_json("#{@configuration.server_url}/api/login", {}, hash) do |result|
53
+ auth_token = result.body['tn']
54
+ expire_time = result.body['timeOut'] - 1000
55
+ @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, expire_time) # token will be expired after 2 hours
56
+ yield(auth_token)
57
+ end
58
+ end
17
59
 
18
- def login_if_required
19
- auth_token = get_auth_token
20
- if Jieshun::Parking.always_login || auth_token.nil? || auth_token.empty?
21
- hash = { pno: @configuration.pno, secret: @configuration.secret }
22
- @http_client.post_json("#{@configuration.server_url}/api/login", {}, hash) do |result|
23
- auth_token = result.body['tn']
24
- expire_time = result.body['timeOut'] - 1000
25
- @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, expire_time) # token will be expired after 2 hours
26
- yield(auth_token)
27
- end
28
- else
29
- yield(auth_token)
30
- end
31
- end
60
+ def get_picture_base64(file_path)
61
+ data_items = []
62
+ data_items << { filePath: file_path }
63
+ unify_call("/api/pic/picSearch", data_items.to_json) do |result|
64
+ image = result.body['dataItems'].first['image']
65
+ mime_type = detect_mime_type(image)
66
+ yield({ mime_type_prefix: "data:#{mime_type};base64,", content: image })
67
+ end
68
+ end
32
69
 
33
- def get_picture_base64(file_path)
34
- data_items = []
35
- data_items << { filePath: file_path }
36
- unify_call("/api/pic/picSearch", data_items.to_json) do |result|
37
- image = result.body['dataItems'].first['image']
38
- mime_type = detect_mime_type(image)
39
- yield( { mime_type_prefix: "data:#{mime_type};base64,", content: image } )
40
- end
41
- end
70
+ def detect_mime_type(base64_content)
71
+ return "application/pdf" if content_matches?(base64_content, ['JVBERi0'])
72
+ return "image/gif" if content_matches?(base64_content, ['R0lGODdh', 'R0lGODlh'])
73
+ return "image/png" if content_matches?(base64_content, ['iVBORw0KGgo'])
74
+ return "image/jpg" if content_matches?(base64_content, ['/9j/'])
75
+ return "image/bmp" if content_matches?(base64_content, ['Qk'])
76
+ "application/octet-stream"
77
+ end
42
78
 
43
- def detect_mime_type(base64_content)
44
- return "application/pdf" if content_matches?(base64_content, ['JVBERi0'])
45
- return "image/gif" if content_matches?(base64_content, ['R0lGODdh', 'R0lGODlh'])
46
- return "image/png" if content_matches?(base64_content, ['iVBORw0KGgo'])
47
- return "image/jpg" if content_matches?(base64_content, ['/9j/'])
48
- return "image/bmp" if content_matches?(base64_content, ['Qk'])
49
- "application/octet-stream"
50
- end
79
+ def content_matches?(base64_content, prefixes)
80
+ prefixes.any? { |prefix| base64_content.start_with?(prefix) }
81
+ end
51
82
 
52
- def content_matches?(base64_content, prefixes)
53
- prefixes.any? { |prefix| base64_content.start_with?(prefix) }
54
- end
83
+ def unify_call(api_path, data_items)
84
+ login_if_required do |auth_token|
85
+ ts = Time.now.strftime("%Y%m%d%H%M%S%L")
86
+ sn = generate_signature("#{@configuration.secret}#{ts}#{data_items}")
87
+ hash = {
88
+ pno: @configuration.pno,
89
+ tn: auth_token,
90
+ ts: ts,
91
+ sn: sn,
92
+ dataItems: data_items
93
+ }
94
+ @http_client.post_json("#{@configuration.server_url}/#{api_path}", {}, hash) do |result|
95
+ yield(result)
96
+ end
97
+ end
98
+ end
55
99
 
56
- def unify_call(api_path, data_items)
57
- login_if_required do |auth_token|
58
- ts = Time.now.strftime("%Y%m%d%H%M%S%L")
59
- sn = generate_signature("#{@configuration.secret}#{ts}#{data_items}")
60
- hash = {
61
- pno: @configuration.pno,
62
- tn: auth_token,
63
- ts: ts,
64
- sn: sn,
65
- dataItems: data_items
66
- }
67
-
68
- @http_client.post_json("#{@configuration.server_url}/#{api_path}", { }, hash) do |result|
69
- yield(result)
70
- end
71
-
72
- end
73
- end
74
-
75
- def generate_signature(payload)
76
- md5_string = Digest::MD5.hexdigest(payload)
77
- md5_string.upcase
78
- end
79
-
80
- end
81
- end
100
+ def generate_signature(payload)
101
+ md5_string = Digest::MD5.hexdigest(payload)
102
+ md5_string.upcase
103
+ end
104
+ end
105
+ end
82
106
  end
@@ -7,6 +7,9 @@ module Jieshun
7
7
  require 'uri'
8
8
  require 'json'
9
9
 
10
+ # 设置连接和读取的超时时间(以秒为单位)
11
+ TIMEOUT = 30 # 例如,30 秒超时
12
+
10
13
  def post_form(server_url, headers, hash)
11
14
  post(server_url, 'application/x-www-form-urlencoded', headers, hash) do |result|
12
15
  yield(result)
@@ -24,7 +27,7 @@ module Jieshun
24
27
  req = Net::HTTP::Post.new(uri)
25
28
  headers.each { |k, v| req[k] = v }
26
29
  req["Content-Type"] = content_type
27
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
30
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', read_timeout: TIMEOUT, open_timeout: TIMEOUT) do |http|
28
31
  if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
29
32
  Jieshun::Parking.logger.debug("Jieshun Parking Request, url: #{server_url}, body: #{JSON.pretty_generate(hash)}")
30
33
  end
@@ -35,6 +35,10 @@ module Jieshun
35
35
  redis_client.ttl key
36
36
  end
37
37
 
38
+
39
+ def redis_set_nx_lock(lock_key, expire_time)
40
+ redis_client.set(lock_key, 1, nx: true, ex: expire_time)
41
+ end
38
42
  end
39
43
  end
40
44
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jieshun
4
4
  module Parking
5
- VERSION = "0.6.3"
5
+ VERSION = "0.6.5"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jieshun-parking
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - LCola
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-08 00:00:00.000000000 Z
11
+ date: 2024-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  requirements: []
83
- rubygems_version: 3.0.9
83
+ rubygems_version: 3.2.3
84
84
  signing_key:
85
85
  specification_version: 4
86
86
  summary: 捷顺停车场 API