lark-relay 0.6.5 → 0.6.6

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.
package/README.md CHANGED
@@ -23,9 +23,9 @@ lark-relay take --app <app> --chats oc_xxx --render text
23
23
  lark-relay status
24
24
  ```
25
25
 
26
- 采集在启动时读取 `lark-cli profile list`,每个未被 `--exclude` 排除的 profile 启动一个 bot consumer
26
+ 采集在启动时读取 `lark-cli profile list`,每个 profile 启动一个 bot consumer
27
27
  user 未登录或授权过期不影响 bot 采集,bot 凭据和权限由 `lark-cli event consume --as bot` 检查
28
- 认证或连接失败会记录 CLI 错误并独立退避重试,无需采集的 profile 用 `--exclude` 排除
28
+ 认证或连接失败会记录 CLI 错误并独立退避重试
29
29
  新增或移除 profile 后需重启采集
30
30
  同一 app 的事件总线只允许一个实例,本地互斥锁按 `LARK_RELAY_HOME` 隔离
31
31
 
@@ -83,14 +83,14 @@ user 未登录或授权过期不影响 bot 采集,bot 凭据和权限由 `lark-c
83
83
  ## macOS 常驻部署
84
84
 
85
85
  - 使用 LaunchDaemon + UserName,开机即起,不依赖 GUI 登录
86
- - ProgramArguments 写可执行文件的绝对路径,显式设置 HOME/PATH/UTF-8 locale
86
+ - ProgramArguments 写可执行文件的绝对路径,显式设置 HOME/PATH
87
87
  - KeepAlive 使用 SuccessfulExit=false;日志路径父目录须预先创建
88
88
  - 代码升级后用 `kickstart -k`,修改 plist 后用 `bootout`、等 label 释放、再 `bootstrap`
89
89
 
90
90
  日志直写 stderr,每行带 ISO 时间戳,不做轮转
91
91
  需要缩减日志时截断文件,不要删除或替换 launchd 持有的文件
92
92
  `status` 中 collect running 只说明主进程在跑,各 app 是否连接成功需查看采集日志
93
- `collect.profiles` 列出已配置 profile,不表示正在采集,也不反映 collect 的 `--exclude`
93
+ `collect.profiles` 列出已配置 profile,不表示正在采集
94
94
  profile 查询失败时 `status` 保留本地状态并以 exit 1 返回,错误见 `collect.profileError` 或文本输出
95
95
  某个 app 有损坏事件时同样以 exit 1 返回,错误见该 app 的 `error` 字段或文本中的 ⚠ 标记
96
96
 
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict'
3
3
 
4
- require('../lib/utf8').ensureUtf8()
5
4
  process.title = 'lark-relay-collect'
6
5
 
7
6
  const { parseArgs, numberArg } = require('../lib/args')
@@ -9,7 +8,7 @@ const { COLLECT_HELP } = require('../lib/help')
9
8
  const VERSION = require('../package.json').version
10
9
 
11
10
  async function main() {
12
- const a = parseArgs(process.argv.slice(2), { keys: ['exclude', 'retain'], flags: ['version'] })
11
+ const a = parseArgs(process.argv.slice(2), { keys: ['retain'], flags: ['version'] })
13
12
  if (a.help || a.version) {
14
13
  process.stdout.write(`${a.version ? VERSION : COLLECT_HELP}\n`)
15
14
  return 0
@@ -20,10 +19,7 @@ async function main() {
20
19
  return 2
21
20
  }
22
21
  const { runCollect } = require('../lib/collect')
23
- return runCollect({
24
- exclude: a.exclude ? a.exclude.split(',').map((s) => s.trim()).filter(Boolean) : [],
25
- retain,
26
- })
22
+ return runCollect({ retain })
27
23
  }
28
24
 
29
25
  main()
package/bin/lark-relay.js CHANGED
@@ -1,8 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict'
3
3
 
4
- require('../lib/utf8').ensureUtf8()
5
-
6
4
  const { parseArgs, numberArg } = require('../lib/args')
7
5
  const help = require('../lib/help')
8
6
  const VERSION = require('../package.json').version
package/lib/collect.js CHANGED
@@ -139,7 +139,6 @@ async function runCollect(opts) {
139
139
  return 1
140
140
  }
141
141
 
142
- const exclude = new Set(opts.exclude || [])
143
142
  let profiles
144
143
  try {
145
144
  profiles = await larkcli.listProfiles()
@@ -154,24 +153,18 @@ async function runCollect(opts) {
154
153
  return 1
155
154
  }
156
155
 
157
- const chosen = profiles.filter((name) => !exclude.has(name))
158
- const skipped = profiles.filter((name) => exclude.has(name))
159
-
160
- if (skipped.length) {
161
- logLine(`跳过 --exclude: ${skipped.join(' ')}`)
162
- }
163
- if (!chosen.length) {
164
- logLine('error: 没有待采集的 profile,检查 `lark-cli profile list` 和 --exclude')
156
+ if (!profiles.length) {
157
+ logLine('error: 没有待采集的 profile,检查 `lark-cli profile list`')
165
158
  return 1
166
159
  }
167
160
 
168
161
  logLine(
169
- `lark-relay-collect: ${chosen.length}/${profiles.length} profiles → ${paths.store}\n` +
170
- ` ${chosen.join(' ')}\n` +
162
+ `lark-relay-collect: ${profiles.length} profiles → ${paths.store}\n` +
163
+ ` ${profiles.join(' ')}\n` +
171
164
  ` event_key=${EVENT_KEY} store 保留 ${opts.retain}天`,
172
165
  )
173
166
 
174
- const collectors = chosen.map((name) => new AppCollector(name))
167
+ const collectors = profiles.map((name) => new AppCollector(name))
175
168
  for (const c of collectors) c.start()
176
169
 
177
170
  // 只回收超期事件,保留消费者的断点
package/lib/help.js CHANGED
@@ -40,21 +40,20 @@ const COLLECT_HELP = `lark-relay-collect -- 常驻收集 im.message.receive_v1
40
40
  lark-relay-collect
41
41
  lark-relay status
42
42
 
43
- 启动时读取 lark-cli profile list,每个未被 --exclude 排除的 profile 启动一个 bot consumer
43
+ 启动时读取 lark-cli profile list,每个 profile 启动一个 bot consumer
44
44
  不依赖 user 登录态,bot 凭据和权限由 lark-cli 检查;失败会记录并退避重试
45
45
  新增或移除 profile 后需重启采集
46
46
  每 app 独立退避重连,断线期间的消息无法回放
47
47
  同一 app 只允许一个事件总线实例,接管前先停止现有采集
48
48
 
49
49
  参数
50
- --exclude <apps> 排除指定 profile,逗号分隔
51
50
  --retain N 事件保留的整数天数,默认 3;每小时回收,启动时也执行
52
51
  -h, --help 用法
53
52
  -v, --version 版本
54
53
 
55
54
  macOS 常驻部署
56
55
  使用 LaunchDaemon + UserName,开机启动且不依赖 GUI 登录
57
- ProgramArguments 写绝对路径,显式设置 HOME/PATH/UTF-8 locale
56
+ ProgramArguments 写绝对路径,显式设置 HOME/PATH
58
57
  KeepAlive 使用 SuccessfulExit=false,日志路径的父目录须已存在
59
58
  sudo launchctl bootstrap system /Library/LaunchDaemons/<label>.plist
60
59
  修改 plist 后需 bootout + bootstrap,代码升级后用 kickstart -k
package/lib/paths.js CHANGED
@@ -48,12 +48,13 @@ function readDir(dir, options) {
48
48
  }
49
49
  }
50
50
 
51
- // stamp 在进程内严格单调,文件名按 stamp/pid/seq 数值排序
52
- let lastStamp = 0n
51
+ // stamp(毫秒)在进程内严格单调,文件名按 stamp/pid/seq 数值排序:
52
+ // 同毫秒内 seq 保序,跨进程由 pid 防撞名
53
+ let lastStamp = 0
53
54
 
54
55
  function eventFilename(seq) {
55
- const wall = BigInt(Date.now()) * 1000000n
56
- lastStamp = wall > lastStamp ? wall : lastStamp + 1n
56
+ const wall = Date.now()
57
+ lastStamp = wall > lastStamp ? wall : lastStamp + 1
57
58
  return `${lastStamp}_${process.pid}_${seq}.json`
58
59
  }
59
60
 
package/lib/store.js CHANGED
@@ -36,7 +36,7 @@ const NAME_RE = /^(\d+)_(\d+)_(\d+)\.json$/
36
36
  function parseKey(name) {
37
37
  const m = NAME_RE.exec(name)
38
38
  if (!m) throw new Error(`事件文件名无效:${name}`)
39
- return { stamp: BigInt(m[1]), pid: Number(m[2]), seq: Number(m[3]) }
39
+ return { stamp: Number(m[1]), pid: Number(m[2]), seq: Number(m[3]) }
40
40
  }
41
41
 
42
42
  function isEventName(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lark-relay",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Lark event relay: collect events to disk, take a batch when you need it.",
5
5
  "keywords": [
6
6
  "lark",
package/lib/utf8.js DELETED
@@ -1,15 +0,0 @@
1
- 'use strict'
2
-
3
- // UTF-8 兜底:launchd 环境无 LANG -> C locale。虽然 Node 的字符串处理
4
- // 不像 bash 那样按字节切片,但子进程(lark-cli)会继承 locale,中文仍会被切坏。
5
- //
6
- // 两个 bin(lark-relay / lark-relay-collect)都要,故抽成模块 —— 复制两份会漂移。
7
- // 必须在任何 spawn 之前执行,所以两个入口都在最顶上 require 它。
8
- function ensureUtf8(env = process.env) {
9
- if (!/utf-?8/i.test(env.LC_ALL || env.LC_CTYPE || env.LANG || '')) {
10
- env.LANG = 'C.UTF-8'
11
- env.LC_ALL = 'C.UTF-8'
12
- }
13
- }
14
-
15
- module.exports = { ensureUtf8 }