mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
41692b7041
* feat(apps): add cache debug commands (+cache-get/-delete/-clear) Add three apps-domain cache debug shortcuts for inspecting/clearing an app's runtime cache: - +cache-get: read a business key's value + metadata (hit/miss) - +cache-delete: delete a single key (idempotent, write) - +cache-clear: clear all cache in an environment (high-risk-write, --yes) value renders raw on --format json, deserialized on --format pretty; value_size_bytes is computed CLI-side; --environment auto-selects the branch when omitted. Includes unit tests (hit/miss/dry-run/confirmation) and the lark-apps cache skill reference. * fix(apps): normalize cache numeric output fields and tidy comments Follow-up hardening for the cache debug commands (+cache-get/-delete/-clear): - Normalize ttl_ms / deleted_key_count via a new cacheInt() helper so --format json emits a stable JSON number (or null) regardless of whether the server sends the value as a number or a string. Aligns with the repo convention that numeric wire fields may arrive as strings; previously these were passed through raw, leaving the output type at the server's mercy. - Add unit tests locking the string-wire -> JSON number contract for both cache-get ttl_ms and cache-delete deleted_key_count. - Tidy two comments: soften cacheBool's speculative "historical wire form" claim to a defensive-tolerance note, and drop implementation jargon from cache-delete's risk-level rationale.
76 lines
2.5 KiB
Go
76 lines
2.5 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||
// SPDX-License-Identifier: MIT
|
||
|
||
package apps
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"io"
|
||
|
||
"github.com/larksuite/cli/shortcuts/common"
|
||
)
|
||
|
||
// AppsCacheDelete deletes a single business cache key (idempotent).
|
||
//
|
||
// DELETE /apps/{app_id}/cache?env=&key=。缓存是派生数据、删单 key 影响面小且可重建,
|
||
// 故定 write(非 high-risk-write、不需 --yes)。目标不存在按幂等成功处理(deleted_key_count=0)。
|
||
var AppsCacheDelete = common.Shortcut{
|
||
Service: appsService,
|
||
Command: "+cache-delete",
|
||
Description: "Delete a single business cache key (idempotent)",
|
||
Risk: "write",
|
||
Tips: []string{
|
||
"Example: lark-cli apps +cache-delete --app-id <app_id> --environment dev --key <key>",
|
||
},
|
||
Scopes: []string{"spark:app:write"},
|
||
AuthTypes: []string{"user"},
|
||
HasFormat: true,
|
||
Flags: []common.Flag{
|
||
{Name: "app-id", Desc: "Miaoda app id", Required: true},
|
||
{Name: "key", Desc: "business cache key", Required: true},
|
||
cacheEnvFlag(),
|
||
},
|
||
Validate: func(ctx context.Context, rctx *common.RuntimeContext) error {
|
||
_, err := requireAppID(rctx.Str("app-id"))
|
||
return err
|
||
},
|
||
DryRun: func(ctx context.Context, rctx *common.RuntimeContext) *common.DryRunAPI {
|
||
appID, _ := requireAppID(rctx.Str("app-id"))
|
||
return common.NewDryRunAPI().
|
||
DELETE(appCachePath(appID)).
|
||
Desc("Delete a Miaoda app runtime cache key").
|
||
Params(dbEnvParams(rctx, map[string]interface{}{"key": rctx.Str("key")}))
|
||
},
|
||
Execute: func(ctx context.Context, rctx *common.RuntimeContext) error {
|
||
appID, err := requireAppID(rctx.Str("app-id"))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
key := rctx.Str("key")
|
||
data, err := rctx.CallAPITyped("DELETE", appCachePath(appID), dbEnvParams(rctx, map[string]interface{}{"key": key}), nil)
|
||
if err != nil {
|
||
return withAppsHint(err, appIDListHint)
|
||
}
|
||
out := map[string]interface{}{
|
||
"key": key,
|
||
"environment": resolvedEnv(data, rctx),
|
||
"deleted_key_count": cacheInt(data["deleted_key_count"]),
|
||
}
|
||
rctx.OutFormat(out, nil, func(w io.Writer) {
|
||
renderCacheDeletePretty(w, out)
|
||
})
|
||
return nil
|
||
},
|
||
}
|
||
|
||
// renderCacheDeletePretty 命中打 "✓ cache deleted",幂等未命中打 "✓ cache already absent"(措辞区分,都成功)。
|
||
func renderCacheDeletePretty(w io.Writer, out map[string]interface{}) {
|
||
key := common.GetString(out, "key")
|
||
if n, ok := numericAsFloat(out["deleted_key_count"]); ok && n > 0 {
|
||
fmt.Fprintf(w, "✓ cache deleted: %s\n", key)
|
||
return
|
||
}
|
||
fmt.Fprintf(w, "✓ cache already absent: %s\n", key)
|
||
}
|