飞书通讯录 ↔ LDAP 同步工具的首个提交。 - internal/feishu: 飞书通讯录客户端、快照与重试 - internal/ldaplib: LDAP 读写与批量操作 - internal/mapping: 飞书部门/用户到 LDAP 条目的映射 - internal/syncer: 同步计划生成、执行与调度 - internal/store: SQLite 台账 - internal/server + internal/webui: 管理后台与内嵌前端产物 - internal/password: SSHA 口令处理 - config.example.yml / Dockerfile / Makefile / web 前端源码 真实凭据(config.yml)、运行时数据(data/、backup/)与构建产物(bin/)不入库。
46 lines
1.1 KiB
Go
46 lines
1.1 KiB
Go
package feishu
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
// isRetryable 判断错误是否值得重试。
|
|
//
|
|
// 只重试可能自愈的传输层问题与飞书的频控/服务端错误;权限、参数错误
|
|
// 立即失败——重试它们既无意义,又会拖慢整轮同步并掩盖真正的问题。
|
|
func isRetryable(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
|
|
// 上下文取消是调用方的决定,不要重试。
|
|
if errors.Is(err, context.Canceled) {
|
|
return false
|
|
}
|
|
// 单次调用的超时值得再试一次;整体超时由外层 ctx 决定。
|
|
if errors.Is(err, context.DeadlineExceeded) {
|
|
return true
|
|
}
|
|
|
|
var netErr net.Error
|
|
if errors.As(err, &netErr) {
|
|
return true
|
|
}
|
|
|
|
msg := strings.ToLower(err.Error())
|
|
for _, s := range []string{
|
|
"timeout", "timed out", "connection reset", "connection refused",
|
|
"broken pipe", "eof", "temporary failure", "too many request",
|
|
"rate limit", "internal server error", "bad gateway",
|
|
"service unavailable", "gateway timeout",
|
|
} {
|
|
if strings.Contains(msg, s) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|