hobots 1.6.0 → 1.7.0
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 +44 -42
- package/dist/index.cjs +105 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -124
- package/dist/index.d.ts +25 -124
- package/dist/index.js +105 -121
- package/dist/index.js.map +1 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +73 -4
- package/dist/protocol.d.ts +73 -4
- package/docs/README.md +8 -8
- package/docs/api-reference.md +40 -42
- package/docs/concepts.md +30 -15
- package/docs/getting-started.md +16 -16
- package/docs/monitor.md +8 -8
- package/docs/protocol.md +20 -22
- package/docs/{manager.md → tasks.md} +18 -18
- package/package.json +2 -7
- package/dist/manager/protocol.cjs +0 -19
- package/dist/manager/protocol.cjs.map +0 -1
- package/dist/manager/protocol.d.cts +0 -72
- package/dist/manager/protocol.d.ts +0 -72
- package/dist/manager/protocol.js +0 -1
- package/dist/manager/protocol.js.map +0 -1
package/dist/protocol.d.cts
CHANGED
|
@@ -1,7 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Tipos do protocolo de tasks do Hobots (agente SDK ↔ servidor).
|
|
3
|
+
*
|
|
4
|
+
* Este arquivo é a fonte de verdade do wire format e não pode importar nada:
|
|
5
|
+
* o app valida os payloads com zod e trava o drift via `satisfies z.ZodType<...>`
|
|
6
|
+
* contra estes tipos (reexportados por `hobots/protocol`).
|
|
7
|
+
*/
|
|
8
|
+
/** Ciclo de vida completo de uma run no servidor. */
|
|
9
|
+
type RunStatus = 'pending' | 'claimed' | 'running' | 'succeeded' | 'failed' | 'canceled';
|
|
10
|
+
/** Subconjunto que o agente pode enviar no PATCH. */
|
|
11
|
+
type RunUpdateStatus = 'running' | 'succeeded' | 'failed';
|
|
12
|
+
type RunLogLevel = 'debug' | 'info' | 'warning' | 'error' | 'success';
|
|
13
|
+
interface RunLogEntry {
|
|
14
|
+
/** ISO 8601 — relógio do agente, apenas para exibição */
|
|
15
|
+
ts: string;
|
|
16
|
+
level: RunLogLevel;
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
interface AgentInfo {
|
|
20
|
+
/** Identidade canônica do agente — correlaciona com o heartbeat de telemetria */
|
|
21
|
+
instance_id: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
/** Versão do SDK */
|
|
24
|
+
version?: string;
|
|
25
|
+
/** Hostname da máquina */
|
|
26
|
+
host?: string;
|
|
27
|
+
/** Tasks registradas no agente */
|
|
28
|
+
tasks?: string[];
|
|
29
|
+
}
|
|
30
|
+
/** POST /v1/tasks/poll */
|
|
31
|
+
interface PollRequest {
|
|
32
|
+
agent?: AgentInfo;
|
|
33
|
+
/** Quantas runs reivindicar de uma vez (1..5). Default: 1 */
|
|
34
|
+
max?: number;
|
|
35
|
+
/** Só entrega runs destas tasks (nomes registrados no agente) */
|
|
36
|
+
tasks?: string[];
|
|
37
|
+
}
|
|
38
|
+
interface RunDescriptor {
|
|
39
|
+
id: string;
|
|
40
|
+
task: string;
|
|
41
|
+
params: Record<string, unknown>;
|
|
42
|
+
form: {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
} | null;
|
|
46
|
+
/** Origem da run: 'hobots' | 'link' | 'schedule' (informativo) */
|
|
47
|
+
source: string;
|
|
48
|
+
/** ISO 8601 (relógio do servidor) */
|
|
49
|
+
created_at: string;
|
|
50
|
+
}
|
|
51
|
+
interface PollResponse {
|
|
52
|
+
runs: RunDescriptor[];
|
|
53
|
+
}
|
|
54
|
+
interface RunError {
|
|
55
|
+
/** ex.: nome da classe do erro */
|
|
56
|
+
type?: string;
|
|
57
|
+
message: string;
|
|
58
|
+
stack?: string;
|
|
59
|
+
}
|
|
60
|
+
/** PATCH /v1/tasks/runs/{id} — 'running' pode repetir com logs incrementais */
|
|
61
|
+
interface RunUpdateRequest {
|
|
62
|
+
status: RunUpdateStatus;
|
|
63
|
+
/** Apenas com status 'failed' */
|
|
64
|
+
error?: RunError;
|
|
65
|
+
/** Delta desde o último envio — o servidor concatena */
|
|
66
|
+
logs?: RunLogEntry[];
|
|
67
|
+
}
|
|
68
|
+
interface RunUpdateResponse {
|
|
69
|
+
ok: true;
|
|
70
|
+
}
|
|
2
71
|
|
|
3
72
|
/**
|
|
4
|
-
* Tipos do protocolo
|
|
73
|
+
* Tipos do protocolo do Hobots (SDK → servidor).
|
|
5
74
|
*
|
|
6
75
|
* Este arquivo é a fonte de verdade do wire format e só pode reexportar tipos:
|
|
7
76
|
* o app valida os payloads com zod e trava o drift via `satisfies z.ZodType<...>`
|
|
@@ -82,7 +151,7 @@ interface TransactionPayload {
|
|
|
82
151
|
tags?: Record<string, string>;
|
|
83
152
|
release?: string;
|
|
84
153
|
environment?: string;
|
|
85
|
-
/** Correlaciona esta transaction a uma execução
|
|
154
|
+
/** Correlaciona esta transaction a uma execução de task (ctx.tx dentro de um task handler) */
|
|
86
155
|
run_id?: string;
|
|
87
156
|
}
|
|
88
157
|
type CheckInStatus = 'in_progress' | 'ok' | 'error';
|
|
@@ -130,4 +199,4 @@ interface Envelope {
|
|
|
130
199
|
items: EnvelopeItem[];
|
|
131
200
|
}
|
|
132
201
|
|
|
133
|
-
export type { Breadcrumb, CheckInPayload, CheckInStatus, Envelope, EnvelopeItem, EventPayload, EventUser, ExceptionData, HeartbeatPayload, Severity, SpanData, SpanStatus, StackFrame, TransactionPayload };
|
|
202
|
+
export type { AgentInfo, Breadcrumb, CheckInPayload, CheckInStatus, Envelope, EnvelopeItem, EventPayload, EventUser, ExceptionData, HeartbeatPayload, PollRequest, PollResponse, RunDescriptor, RunError, RunLogEntry, RunLogLevel, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, Severity, SpanData, SpanStatus, StackFrame, TransactionPayload };
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,7 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Tipos do protocolo de tasks do Hobots (agente SDK ↔ servidor).
|
|
3
|
+
*
|
|
4
|
+
* Este arquivo é a fonte de verdade do wire format e não pode importar nada:
|
|
5
|
+
* o app valida os payloads com zod e trava o drift via `satisfies z.ZodType<...>`
|
|
6
|
+
* contra estes tipos (reexportados por `hobots/protocol`).
|
|
7
|
+
*/
|
|
8
|
+
/** Ciclo de vida completo de uma run no servidor. */
|
|
9
|
+
type RunStatus = 'pending' | 'claimed' | 'running' | 'succeeded' | 'failed' | 'canceled';
|
|
10
|
+
/** Subconjunto que o agente pode enviar no PATCH. */
|
|
11
|
+
type RunUpdateStatus = 'running' | 'succeeded' | 'failed';
|
|
12
|
+
type RunLogLevel = 'debug' | 'info' | 'warning' | 'error' | 'success';
|
|
13
|
+
interface RunLogEntry {
|
|
14
|
+
/** ISO 8601 — relógio do agente, apenas para exibição */
|
|
15
|
+
ts: string;
|
|
16
|
+
level: RunLogLevel;
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
interface AgentInfo {
|
|
20
|
+
/** Identidade canônica do agente — correlaciona com o heartbeat de telemetria */
|
|
21
|
+
instance_id: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
/** Versão do SDK */
|
|
24
|
+
version?: string;
|
|
25
|
+
/** Hostname da máquina */
|
|
26
|
+
host?: string;
|
|
27
|
+
/** Tasks registradas no agente */
|
|
28
|
+
tasks?: string[];
|
|
29
|
+
}
|
|
30
|
+
/** POST /v1/tasks/poll */
|
|
31
|
+
interface PollRequest {
|
|
32
|
+
agent?: AgentInfo;
|
|
33
|
+
/** Quantas runs reivindicar de uma vez (1..5). Default: 1 */
|
|
34
|
+
max?: number;
|
|
35
|
+
/** Só entrega runs destas tasks (nomes registrados no agente) */
|
|
36
|
+
tasks?: string[];
|
|
37
|
+
}
|
|
38
|
+
interface RunDescriptor {
|
|
39
|
+
id: string;
|
|
40
|
+
task: string;
|
|
41
|
+
params: Record<string, unknown>;
|
|
42
|
+
form: {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
} | null;
|
|
46
|
+
/** Origem da run: 'hobots' | 'link' | 'schedule' (informativo) */
|
|
47
|
+
source: string;
|
|
48
|
+
/** ISO 8601 (relógio do servidor) */
|
|
49
|
+
created_at: string;
|
|
50
|
+
}
|
|
51
|
+
interface PollResponse {
|
|
52
|
+
runs: RunDescriptor[];
|
|
53
|
+
}
|
|
54
|
+
interface RunError {
|
|
55
|
+
/** ex.: nome da classe do erro */
|
|
56
|
+
type?: string;
|
|
57
|
+
message: string;
|
|
58
|
+
stack?: string;
|
|
59
|
+
}
|
|
60
|
+
/** PATCH /v1/tasks/runs/{id} — 'running' pode repetir com logs incrementais */
|
|
61
|
+
interface RunUpdateRequest {
|
|
62
|
+
status: RunUpdateStatus;
|
|
63
|
+
/** Apenas com status 'failed' */
|
|
64
|
+
error?: RunError;
|
|
65
|
+
/** Delta desde o último envio — o servidor concatena */
|
|
66
|
+
logs?: RunLogEntry[];
|
|
67
|
+
}
|
|
68
|
+
interface RunUpdateResponse {
|
|
69
|
+
ok: true;
|
|
70
|
+
}
|
|
2
71
|
|
|
3
72
|
/**
|
|
4
|
-
* Tipos do protocolo
|
|
73
|
+
* Tipos do protocolo do Hobots (SDK → servidor).
|
|
5
74
|
*
|
|
6
75
|
* Este arquivo é a fonte de verdade do wire format e só pode reexportar tipos:
|
|
7
76
|
* o app valida os payloads com zod e trava o drift via `satisfies z.ZodType<...>`
|
|
@@ -82,7 +151,7 @@ interface TransactionPayload {
|
|
|
82
151
|
tags?: Record<string, string>;
|
|
83
152
|
release?: string;
|
|
84
153
|
environment?: string;
|
|
85
|
-
/** Correlaciona esta transaction a uma execução
|
|
154
|
+
/** Correlaciona esta transaction a uma execução de task (ctx.tx dentro de um task handler) */
|
|
86
155
|
run_id?: string;
|
|
87
156
|
}
|
|
88
157
|
type CheckInStatus = 'in_progress' | 'ok' | 'error';
|
|
@@ -130,4 +199,4 @@ interface Envelope {
|
|
|
130
199
|
items: EnvelopeItem[];
|
|
131
200
|
}
|
|
132
201
|
|
|
133
|
-
export type { Breadcrumb, CheckInPayload, CheckInStatus, Envelope, EnvelopeItem, EventPayload, EventUser, ExceptionData, HeartbeatPayload, Severity, SpanData, SpanStatus, StackFrame, TransactionPayload };
|
|
202
|
+
export type { AgentInfo, Breadcrumb, CheckInPayload, CheckInStatus, Envelope, EnvelopeItem, EventPayload, EventUser, ExceptionData, HeartbeatPayload, PollRequest, PollResponse, RunDescriptor, RunError, RunLogEntry, RunLogLevel, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, Severity, SpanData, SpanStatus, StackFrame, TransactionPayload };
|
package/docs/README.md
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# Documentação — hobots
|
|
2
2
|
|
|
3
|
-
SDK JavaScript da **Hobots** para instrumentar funcionários digitais (RPAs) e integrações. Cliente HTTP puro, sem dependências de runtime, para Node 18+ (
|
|
3
|
+
SDK JavaScript da **Hobots** para instrumentar funcionários digitais (RPAs) e integrações. Cliente HTTP puro, sem dependências de runtime, para Node 18+ (a telemetria também roda no browser para captura de erros).
|
|
4
4
|
|
|
5
5
|
O SDK expõe **duas capabilities** autenticadas pelo **mesmo Client Secret do projeto**, configuradas em **um único `init()`** com **um único import** (`import * as Hobots from 'hobots'`):
|
|
6
6
|
|
|
7
7
|
| Capability | Como habilita | Para quê |
|
|
8
8
|
| --- | --- | --- |
|
|
9
|
-
| **
|
|
10
|
-
| **
|
|
9
|
+
| **Telemetria** | sempre ativa no `init()` | O que o programa **emite** sozinho: erros com stack trace (módulo **Issues**), performance (transactions/spans) e heartbeats de uptime (módulo **Agentes**), check-ins de cron (módulo **Monitores**). Instala handlers globais de erro; os timers são `unref`'d, então nunca seguram o processo vivo. |
|
|
10
|
+
| **Tasks** | `tasks: true` (ou opções) no `init()` | Execução **sob demanda**: o agente faz polling no app, executa handlers registrados e reporta status/logs — o módulo **Solicitações**. `start()` **mantém o processo vivo** até `stop()`/`close()`. |
|
|
11
11
|
|
|
12
12
|
## Páginas
|
|
13
13
|
|
|
14
14
|
Se termos como transaction, span, breadcrumb, tag, context, extra, flush e close ainda não são familiares, comece por **Conceitos** — as outras páginas assumem esse vocabulário.
|
|
15
15
|
|
|
16
16
|
- [Conceitos](./concepts.md) — o vocabulário: o que cada coisa é, por que existe e quando escolher uma em vez da outra.
|
|
17
|
-
- [Getting started](./getting-started.md) — instalação, Client Secret, o `init` único,
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
17
|
+
- [Getting started](./getting-started.md) — instalação, Client Secret, o `init` único, telemetria e tasks.
|
|
18
|
+
- [Telemetria](./monitor.md) — erros, breadcrumbs, escopo, transactions/spans, crons e heartbeat.
|
|
19
|
+
- [Tasks](./tasks.md) — registro de handlers, `RunContext`, cancelamento, concorrência, idempotência.
|
|
20
20
|
- [Referência de API](./api-reference.md) — todas as funções e tabelas de opções com defaults.
|
|
21
21
|
- [Protocolo & transporte](./protocol.md) — o Client Secret, endpoints, envelope, retries e onde vive o claim atômico.
|
|
22
22
|
|
|
@@ -28,13 +28,13 @@ import * as Hobots from 'hobots';
|
|
|
28
28
|
// O Client Secret do projeto — copie em Configurações → Projetos no app
|
|
29
29
|
const clientSecret = 'hb_<64 hex>';
|
|
30
30
|
|
|
31
|
-
// Um init só: telemetria sempre ativa;
|
|
31
|
+
// Um init só: telemetria sempre ativa; tasks habilita a execução sob demanda.
|
|
32
32
|
// O instanceId é a identidade única — o robô aparece como um agente só no painel.
|
|
33
33
|
Hobots.init({
|
|
34
34
|
clientSecret,
|
|
35
35
|
instanceId: 'vm-cliente-01',
|
|
36
36
|
heartbeat: true,
|
|
37
|
-
|
|
37
|
+
tasks: true,
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
Hobots.register('processar-nfe', async (params, ctx) => {
|
package/docs/api-reference.md
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
| Import | Conteúdo |
|
|
6
6
|
| --- | --- |
|
|
7
|
-
| `hobots` | Tudo: `init` único, funções
|
|
8
|
-
| `hobots/protocol` | Tipos do wire format (
|
|
7
|
+
| `hobots` | Tudo: `init` único, funções de telemetria, `register`/`start`/`stop` de tasks, `close`, classes (`Client`, `Scope`, `Transaction`, `Span`), `DEFAULT_BASE_URL`, `scrubSecrets` e tipos. |
|
|
8
|
+
| `hobots/protocol` | Tipos do wire format (telemetria e tasks). |
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Telemetria — funções
|
|
13
13
|
|
|
14
14
|
| Função | Assinatura | Retorno |
|
|
15
15
|
| --- | --- | --- |
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
| `setContext` | `setContext(name: string, ctx: Record<string,unknown> \| null): void` | — |
|
|
24
24
|
| `setExtra` | `setExtra(key: string, value: unknown): void` | — |
|
|
25
25
|
| `withScope` | `withScope<T>(cb: (scope: Scope) => T): T` | retorno do callback |
|
|
26
|
-
| `startTransaction` | `startTransaction(name: string, op?: string): Transaction` | transaction |
|
|
26
|
+
| `startTransaction` | `startTransaction(name: string, op?: string): Transaction` | transaction (dentro de um handler de task, a própria `ctx.tx`) |
|
|
27
27
|
| `checkIn` | `checkIn(options: CheckInOptions): string \| undefined` | check_in_id |
|
|
28
28
|
| `withMonitor` | `withMonitor<T>(slug: string, fn: () => T \| Promise<T>, options?: WithMonitorOptions): Promise<T>` | retorno de `fn` |
|
|
29
29
|
| `flush` | `flush(timeoutMs = 5_000): Promise<boolean>` | enviou tudo dentro do prazo? |
|
|
30
|
-
| `close` | `close(timeoutMs = 5_000): Promise<boolean>` | para o
|
|
30
|
+
| `close` | `close(timeoutMs = 5_000): Promise<boolean>` | para o polling de tasks (aguarda runs) + heartbeat + flush final do transport |
|
|
31
31
|
|
|
32
32
|
### O que cada função faz
|
|
33
33
|
|
|
34
34
|
Os conceitos por trás dessas chamadas estão em [Conceitos](./concepts.md); aqui está o que cada uma **faz** e o que **devolve**.
|
|
35
35
|
|
|
36
|
-
- **`init(options)`** — cria o cliente, instala os handlers globais de erro (a menos que `captureUnhandled: false`), inicia o heartbeat se configurado e cria o agente
|
|
37
|
-
- **`getClient()`** — devolve o cliente atual ou `undefined` se o `init()` nunca rodou. Útil para checar se o SDK está ativo.
|
|
36
|
+
- **`init(options)`** — cria o cliente, instala os handlers globais de erro (a menos que `captureUnhandled: false`), inicia o heartbeat se configurado e cria o agente de tasks se `tasks` foi passado. Chamar de novo **substitui** o cliente e o agente (os handlers registrados com `register` são preservados; o [scope](./concepts.md#scope) **não** é limpo). Chame uma vez, o mais cedo possível.
|
|
37
|
+
- **`getClient()`** — devolve o cliente atual ou `undefined` se o `init()` nunca rodou. Útil para checar se o SDK está ativo. A config resolvida (URL base e endpoints) é acessível via `getClient()?.config` (veja abaixo).
|
|
38
38
|
- **`captureException(error, hint?)`** — monta um [evento](./concepts.md#evento) a partir da exceção (tipo, mensagem, stack trace), mescla o scope e enfileira. O `level` é `error` a menos que você passe outro no `hint`.
|
|
39
39
|
- **`captureMessage(message, level = 'info', hint?)`** — mesma coisa, sem exceção: um evento só com texto. Bom para marcos (`'success'`) e avisos que não são erro.
|
|
40
40
|
> **Atenção:** as duas devolvem um `event_id` **mesmo quando o evento foi descartado** por [amostragem](./concepts.md#amostragem-samplerate-e-tracessamplerate) ou por [`beforeSend`](./concepts.md#beforesend). O retorno não prova que algo foi enviado — só é `undefined` quando o `init()` não foi chamado.
|
|
@@ -44,21 +44,21 @@ Os conceitos por trás dessas chamadas estão em [Conceitos](./concepts.md); aqu
|
|
|
44
44
|
- **`setContext(name, ctx | null)`** — define um [context](./concepts.md#context) nomeado. Passar `null` **apaga o grupo inteiro**. Os grupos `runtime` e `os` são injetados pelo SDK em todo evento.
|
|
45
45
|
- **`setExtra(key, value)`** — anexa um dado livre, sem estrutura e sem índice. Conceito e critério de escolha em [Extra](./concepts.md#extra).
|
|
46
46
|
- **`withScope(cb)`** — roda o callback com um **clone** do scope e restaura o original no fim; devolve o que o callback devolver. É **síncrono** — um `await` dentro do callback não isola de código concorrente. Conceito: [withScope](./concepts.md#withscope).
|
|
47
|
-
- **`startTransaction(name, op?)`** — abre uma [transaction](./concepts.md#transaction) de performance. A decisão de [amostragem](./concepts.md#amostragem-samplerate-e-tracessamplerate) acontece **aqui**, não no `finish()`. Nada é enviado até o `finish()`. Dentro de um handler
|
|
47
|
+
- **`startTransaction(name, op?)`** — abre uma [transaction](./concepts.md#transaction) de performance. A decisão de [amostragem](./concepts.md#amostragem-samplerate-e-tracessamplerate) acontece **aqui**, não no `finish()`. Nada é enviado até o `finish()`. **Dentro de um handler de task**, devolve a [transaction da própria run](./concepts.md#transaction-de-run-ctxtx) (`ctx.tx`) em vez de criar uma segunda — cada execução tem exatamente uma transaction; fora de um handler, cria uma transaction nova, sem `run_id`.
|
|
48
48
|
- **`checkIn(options)`** — envia um [check-in](./concepts.md#check-in) avulso e devolve o `check_in_id`. Reaproveite o id do `in_progress` para fechar a execução com `ok`/`error`.
|
|
49
49
|
- **`withMonitor(slug, fn, options?)`** — envolve `fn` no par de check-ins (`in_progress` → `ok`/`error`) medindo a duração, e devolve o que `fn` devolver. Em caso de erro, fecha como `error`, captura o evento com a tag `monitor: <slug>` e **relança** a exceção. Passe `schedule` para o servidor criar/atualizar o monitor sozinho e detectar execução perdida.
|
|
50
50
|
- **`flush(timeoutMs = 5_000)`** → `Promise<boolean>` — empurra a fila do transport e aguarda os envios em andamento. `true` = tudo saiu no prazo; `false` = o SDK parou de esperar (os envios em voo seguem tentando). O SDK **continua utilizável** depois. Conceito: [Fila, flush e close](./concepts.md#fila-flush-e-close).
|
|
51
51
|
- **`close(timeoutMs = 5_000)`** → `Promise<boolean>` — encerra tudo na ordem agente → heartbeat → flush final. O `timeoutMs` é gasto **duas vezes** (espera das runs, depois flush). Depois do `close()` o transport está fechado e todo item novo é descartado com aviso no console; não há `reopen()`. Conceito: [Fila, flush e close](./concepts.md#fila-flush-e-close).
|
|
52
52
|
|
|
53
|
-
Classes exportadas: `Client`, `Scope`, `Transaction`, `Span`.
|
|
53
|
+
Classes exportadas: `Client`, `Scope`, `Transaction`, `Span`. A resolução da credencial nos endpoints é interna ao `init()` (constante `DEFAULT_BASE_URL = 'https://api2.hobots.app'`, exportada; em desenvolvimento a env `HOBOTS_API_URL` sobrescreve a URL base). A config resolvida fica acessível em `getClient()?.config`:
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
56
|
+
getClient()?.config; // {
|
|
57
|
+
// key: string; — Client Secret do projeto (vai no Authorization: Bearer, nunca na URL)
|
|
58
|
+
// baseUrl: string; — DEFAULT_BASE_URL, ou HOBOTS_API_URL em desenvolvimento
|
|
59
|
+
// ingestEndpoint: string; — <baseUrl>/v1/ingest
|
|
60
|
+
// tasksBaseUrl: string; — <baseUrl>/v1/tasks
|
|
61
|
+
// }
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
### Métodos de `Transaction` / `Span` / `Scope`
|
|
@@ -72,25 +72,23 @@ Todos encadeáveis, exceto `finish()` e `toJSON()`.
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
-
##
|
|
75
|
+
## Tasks — funções
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
Habilitadas com `tasks: true` (ou `TasksOptions`) no `init()` único. Todas exportadas do import raiz `hobots`:
|
|
78
78
|
|
|
79
79
|
| Função | Assinatura |
|
|
80
80
|
| --- | --- |
|
|
81
|
-
| `register` | `register<P>(task: string, handler:
|
|
82
|
-
| `start` | `start(): void` — lança se o `init()` não configurou `
|
|
83
|
-
| `stop` | `stop(timeoutMs = 30_000): Promise<boolean>` — para só o
|
|
81
|
+
| `register` | `register<P>(task: string, handler: TaskHandler<P>): void` |
|
|
82
|
+
| `start` | `start(): void` — lança se o `init()` não configurou `tasks` ou sem tasks registradas |
|
|
83
|
+
| `stop` | `stop(timeoutMs = 30_000): Promise<boolean>` — para só o polling de tasks; a telemetria continua |
|
|
84
84
|
|
|
85
85
|
### O que cada função faz
|
|
86
86
|
|
|
87
|
-
- **`register(task, handler)`** — associa um handler ao `task_slug` configurado no formulário do app. Registre **antes** de `start()`; pode ser chamado antes do `init()`. Registrar o mesmo `task` duas vezes **sobrescreve** o handler (com aviso no console). Se o `init()` não habilitou
|
|
88
|
-
- **`start()`** — começa o polling. **Mantém o processo vivo** até `stop()`/`close()` — o timer não é `unref`'d, ao contrário dos
|
|
89
|
-
- **`stop(timeoutMs = 30_000)`** → `Promise<boolean>` — encerra o polling e aguarda as [runs](./concepts.md#run) ativas terminarem. Para **só
|
|
90
|
-
|
|
91
|
-
Classes/erros exportados: `ManagerAgent`, `ManagerApi`, `ManagerApiError`.
|
|
87
|
+
- **`register(task, handler)`** — associa um handler ao `task_slug` configurado no formulário do app (**Configurações → Formulários**). Registre **antes** de `start()`; pode ser chamado antes do `init()`. Registrar o mesmo `task` duas vezes **sobrescreve** o handler (com aviso no console). Se o `init()` não habilitou as tasks, o SDK avisa e não faz nada. Tipagem dos params: `register<{ lote: number }>(…)`.
|
|
88
|
+
- **`start()`** — começa o polling. **Mantém o processo vivo** até `stop()`/`close()` — o timer não é `unref`'d, ao contrário dos da telemetria. Lança se o `init()` não configurou `tasks` ou se nenhuma task foi registrada. Também instala os handlers de saída (SIGINT/SIGTERM/erro fatal) que reportam as runs ativas como `AgentTerminated`, a menos que `installExitHandlers: false`.
|
|
89
|
+
- **`stop(timeoutMs = 30_000)`** → `Promise<boolean>` — encerra o polling e aguarda as [runs](./concepts.md#run) ativas terminarem. Para **só as tasks**: a telemetria (heartbeat, captura de erros) continua funcionando. Devolve `false` se estourou o timeout — as runs que ainda estavam rodando são reportadas como `AgentTerminated`. Para encerrar tudo, use [`close()`](./concepts.md#fila-flush-e-close).
|
|
92
90
|
|
|
93
|
-
No poll, o agente se identifica com `
|
|
91
|
+
No poll, o agente se identifica com `AgentInfo` (`hobots/protocol`): o campo `instance_id` (o `instanceId` do `init()`) é a identidade canônica do agente — a mesma do heartbeat de telemetria, então os dois canais convergem em um agente no painel.
|
|
94
92
|
|
|
95
93
|
---
|
|
96
94
|
|
|
@@ -103,14 +101,14 @@ No poll, o agente se identifica com `ManagerAgentInfo` (`hobots/protocol`): o ca
|
|
|
103
101
|
| `clientSecret` | `string` | — | **obrigatório**; o Client Secret do projeto (`hb_<64 hex>`), copiado em **Configurações → Projetos** |
|
|
104
102
|
| `environment` | `string` | `'production'` | ambiente lógico |
|
|
105
103
|
| `release` | `string` | — | versão do programa, ex. `robo-nfe@1.4.2` |
|
|
106
|
-
| `instanceId` | `string` | **obrigatório** | identidade única da instância; heartbeat
|
|
104
|
+
| `instanceId` | `string` | **obrigatório** | identidade única da instância; heartbeat e poll de tasks convergem nela |
|
|
107
105
|
| `tags` | `Record<string,string>` | — | tags aplicadas a todos os eventos |
|
|
108
106
|
| `sampleRate` | `number` | `1` | amostragem de erros (0..1) |
|
|
109
107
|
| `tracesSampleRate` | `number` | `1` | amostragem de transactions (0..1) |
|
|
110
108
|
| `maxBreadcrumbs` | `number` | `100` | tamanho do buffer de breadcrumbs |
|
|
111
109
|
| `captureUnhandled` | `boolean` | `true` | handlers globais de erro |
|
|
112
110
|
| `heartbeat` | `boolean \| HeartbeatOptions` | `false` | heartbeat periódico |
|
|
113
|
-
| `
|
|
111
|
+
| `tasks` | `boolean \| TasksOptions` | `false` | habilita a execução sob demanda (`true` usa defaults) |
|
|
114
112
|
| `beforeSend` | `(event) => event \| null` | — | edita/descarta evento (retorne `null` para descartar) |
|
|
115
113
|
| `debug` | `boolean` | `false` | loga atividade do SDK |
|
|
116
114
|
| `flushIntervalMs` | `number` | `2000` | intervalo do flush automático do transport |
|
|
@@ -155,9 +153,9 @@ O teto da fila do transport (200 itens; ao encher, o **mais antigo** é descarta
|
|
|
155
153
|
| `schedule` | `string` | expressão cron (upsert do monitor) |
|
|
156
154
|
| `timezone` | `string` | fuso do `schedule` |
|
|
157
155
|
|
|
158
|
-
###
|
|
156
|
+
### TasksOptions
|
|
159
157
|
|
|
160
|
-
Valor do campo `
|
|
158
|
+
Valor do campo `tasks` do `InitOptions`. O Client Secret, o `debug` e a identidade (`instanceId`) vêm do `init()`.
|
|
161
159
|
|
|
162
160
|
| Opção | Tipo | Default | Descrição |
|
|
163
161
|
| --- | --- | --- | --- |
|
|
@@ -168,17 +166,17 @@ Valor do campo `manager` do `InitOptions`. O Client Secret, o `debug` e a identi
|
|
|
168
166
|
| `cancelCheckIntervalMs` | `number` | `5000` | heartbeat de cancelamento por run (clamp 1000..15000) — também é o sinal de vida da run (servidor marca `AgentTerminated` após ~60s sem reporte) |
|
|
169
167
|
| `installExitHandlers` | `boolean` | `true` | handlers de SIGINT/SIGTERM/uncaughtException que reportam as runs ativas como `AgentTerminated` antes do processo morrer; nunca interferem quando o programa tem handler próprio |
|
|
170
168
|
|
|
171
|
-
###
|
|
169
|
+
### TaskHandler / RunContext
|
|
172
170
|
|
|
173
171
|
```ts
|
|
174
172
|
// o retorno do handler é ignorado — nada além de status/logs/erro é enviado ao servidor
|
|
175
|
-
type
|
|
173
|
+
type TaskHandler<P = Record<string, unknown>> =
|
|
176
174
|
(params: P, ctx: RunContext) => void | Promise<void>;
|
|
177
175
|
|
|
178
176
|
interface RunContext {
|
|
179
177
|
runId: string;
|
|
180
178
|
task: string;
|
|
181
|
-
log
|
|
179
|
+
log: RunLogger; // ctx.log.debug/info/warn/error/success(message)
|
|
182
180
|
tx: Transaction; // transaction desta run — correlacionada e finalizada pelo SDK
|
|
183
181
|
signal: AbortSignal;
|
|
184
182
|
throwIfCanceled(): void; // lança RunCanceled se o signal já disparou
|
|
@@ -187,8 +185,8 @@ interface RunContext {
|
|
|
187
185
|
```
|
|
188
186
|
|
|
189
187
|
- **`runId` / `task`** — identificam a execução; úteis para correlacionar com os seus próprios logs.
|
|
190
|
-
- **`log(
|
|
191
|
-
- **`tx`** — a [transaction de performance da run](./concepts.md#transaction-de-run-ctxtx). Use `ctx.tx.startChild(op, description)` para medir as etapas; **não** chame `finish()` nela
|
|
188
|
+
- **`log.<level>(message)`** — níveis `debug`, `info`, `warn`, `error` e `success`; enfileira uma linha de log enviada ao app em PATCHes incrementais, e **também imprime no terminal local**. Conceito: [Run](./concepts.md#run).
|
|
189
|
+
- **`tx`** — a [transaction de performance da run](./concepts.md#transaction-de-run-ctxtx). Use `ctx.tx.startChild(op, description)` para medir as etapas; **não** chame `finish()` nela. `startTransaction()` dentro do handler devolve essa mesma transaction.
|
|
192
190
|
- **`signal`** — `AbortSignal` que dispara em cancelamento no app, timeout ou shutdown.
|
|
193
191
|
- **`throwIfCanceled()`** — o ponto de parada de uma linha: lança `RunCanceled` se o `signal` já disparou.
|
|
194
192
|
- **`sleep(ms)`** — espera que respeita o `signal` (rejeita com `RunCanceled` em vez de dormir até o fim). Use no lugar do seu `sleep` em esperas longas.
|
|
@@ -199,7 +197,7 @@ interface RunContext {
|
|
|
199
197
|
|
|
200
198
|
Todos os prazos do SDK num lugar só. A coluna **Onde configura** diz se o valor é seu ou fixo — o que está com `—` é comportamento do SDK ou do servidor e não se muda pelo `init()`.
|
|
201
199
|
|
|
202
|
-
###
|
|
200
|
+
### Telemetria — envio
|
|
203
201
|
|
|
204
202
|
| Tempo | Default | Onde configura | O que acontece |
|
|
205
203
|
| --- | --- | --- | --- |
|
|
@@ -211,20 +209,20 @@ Todos os prazos do SDK num lugar só. A coluna **Onde configura** diz se o valor
|
|
|
211
209
|
| ladder de retry | `1s, 4s, 16s` | — (fixo) | 3 tentativas por envelope; depois ele é descartado. 4xx (exceto 429) não tem retry |
|
|
212
210
|
| heartbeat | `30000` ms | `init({ heartbeat: { intervalMs } })` | bate **imediatamente** no `init()` e depois a cada intervalo; o valor vai no payload e define quanto silêncio o servidor tolera antes de marcar offline |
|
|
213
211
|
|
|
214
|
-
###
|
|
212
|
+
### Tasks — polling e runs
|
|
215
213
|
|
|
216
214
|
| Tempo | Default | Onde configura | O que acontece |
|
|
217
215
|
| --- | --- | --- | --- |
|
|
218
|
-
| poll sem trabalho | `5000` ms (mín. `1000`) | `
|
|
219
|
-
| flush de logs da run | `2000` ms | `
|
|
220
|
-
| heartbeat de cancelamento | `5000` ms (clamp `1000`..`15000`) | `
|
|
221
|
-
| timeout por run | sem timeout | `
|
|
216
|
+
| poll sem trabalho | `5000` ms (mín. `1000`) | `tasks: { pollIntervalMs }` | é só o **teto da espera quando não há nada**: com trabalho na fila o próximo poll é imediato ([drain mode](./concepts.md#drain-mode)) |
|
|
217
|
+
| flush de logs da run | `2000` ms | `tasks: { logFlushIntervalMs }` | ou na hora, ao acumular 20 linhas |
|
|
218
|
+
| heartbeat de cancelamento | `5000` ms (clamp `1000`..`15000`) | `tasks: { cancelCheckIntervalMs }` | detecta cancelamento feito no app **e** é o sinal de vida da run (veja a nota 2) |
|
|
219
|
+
| timeout por run | sem timeout | `tasks: { taskTimeoutMs }` | no estouro dispara `ctx.signal`, libera o slot de concorrência e reporta `TaskTimeout` — **não mata** o handler |
|
|
222
220
|
| `stop(timeoutMs)` | `30000` ms | argumento | espera as runs ativas; no estouro elas são reportadas como `AgentTerminated` |
|
|
223
221
|
| retry do poll | `1s, 4s, 16s` | — (fixo) | erros de rede/5xx |
|
|
224
222
|
| retry com chave rejeitada (401) | `30000` ms | — (fixo) | segue tentando devagar, com log throttled |
|
|
225
223
|
| PATCH do caminho de saída | `~2500` ms | — (fixo) | melhor esforço, sem retry, ao morrer com run ativa |
|
|
226
224
|
| sweep do servidor | `~60000` ms | — (servidor) | run `running` sem reporte por esse tempo vira `failed`/`AgentTerminated`, sem re-entrega |
|
|
227
225
|
|
|
228
|
-
**Nota 1 — `close(timeoutMs)` gasta o tempo duas vezes.** Ele espera as runs
|
|
226
|
+
**Nota 1 — `close(timeoutMs)` gasta o tempo duas vezes.** Ele espera as runs de tasks (`timeoutMs`) e **depois** faz o flush final (`timeoutMs`), em sequência. Pior caso ≈ `2 × timeoutMs`; `close()` sem argumento pode levar até ~35s (30s aguardando runs + 5s de flush). Se o seu SIGTERM tem prazo curto (Kubernetes, systemd), dimensione por aí.
|
|
229
227
|
|
|
230
228
|
**Nota 2 — o teto de 15s do `cancelCheckIntervalMs` existe por causa do sweep de 60s.** Esse heartbeat é o que mantém o `last_report_at` da run atualizado; o clamp garante que o intervalo nunca chegue perto do prazo em que o servidor declara a run morta.
|
package/docs/concepts.md
CHANGED
|
@@ -21,13 +21,13 @@ Os defaults numéricos **não** estão aqui — eles vivem em [Tempos e interval
|
|
|
21
21
|
| [Breadcrumb](#breadcrumb) | Migalha da trilha que levou até o erro | Marcar cada passo relevante do robô |
|
|
22
22
|
| [Transaction](#transaction) | Unidade de trabalho nomeada, com duração | Medir quanto uma rotina inteira demorou |
|
|
23
23
|
| [Span](#span) | Uma etapa medida dentro da transaction | Descobrir **onde** o tempo foi gasto |
|
|
24
|
-
| [ctx.tx](#transaction-de-run-ctxtx) | A transaction que o SDK já abriu para a run | Medir as etapas de um handler
|
|
24
|
+
| [ctx.tx](#transaction-de-run-ctxtx) | A transaction que o SDK já abriu para a run | Medir as etapas de um handler de task |
|
|
25
25
|
| [Amostragem](#amostragem-samplerate-e-tracessamplerate) | Enviar só uma fração do que acontece | Volume alto demais para enviar tudo |
|
|
26
26
|
| [Check-in](#check-in) | Par de avisos "comecei" / "terminei" de um job agendado | Cron que precisa ser vigiado |
|
|
27
27
|
| [Heartbeat](#heartbeat) | Batimento "estou vivo" | Saber que o robô está de pé, mesmo parado |
|
|
28
28
|
| [instanceId](#instanceid) | A identidade da instância do robô | Sempre — é obrigatório no `init()` |
|
|
29
29
|
| [Release e environment](#release-e-environment) | Qual versão, em qual ambiente | Separar produção de homologação; achar a versão que quebrou |
|
|
30
|
-
| [Run](#run) | Uma execução solicitada no app |
|
|
30
|
+
| [Run](#run) | Uma execução solicitada no app | As tasks inteiras giram em volta disso |
|
|
31
31
|
| [Claim](#claim) | O ato de um agente pegar uma run para si | Entender por que dois agentes nunca colidem |
|
|
32
32
|
| [Drain mode](#drain-mode) | O agente acelera o poll enquanto tem trabalho | Entender o ritmo do polling |
|
|
33
33
|
| [Fila, flush e close](#fila-flush-e-close) | Nada é enviado na hora — vai para uma fila | Encerrar o processo sem perder telemetria |
|
|
@@ -35,15 +35,28 @@ Os defaults numéricos **não** estão aqui — eles vivem em [Tempos e interval
|
|
|
35
35
|
|
|
36
36
|
> **Nota de manutenção:** esta página é a fonte canônica das explicações de conceito. As outras páginas da doc, o `README.md` do pacote e os tooltips do app parafraseiam daqui — quando um conceito muda, muda aqui primeiro.
|
|
37
37
|
|
|
38
|
+
## O SDK e os módulos do app
|
|
39
|
+
|
|
40
|
+
Cada API do SDK alimenta um módulo do app da Hobots (app.hobots.app). O mapa:
|
|
41
|
+
|
|
42
|
+
| No SDK | No app |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| **Projeto** — o "funcionário digital"; dono do Client Secret (`hb_…`) que autentica tudo | **Configurações → Projetos** (é lá que você copia a credencial) |
|
|
45
|
+
| **Agente / instância** — o par `(project_id, instance_id)`; heartbeat e poll de tasks convergem nele | Módulo **Agentes** (uptime, performance) |
|
|
46
|
+
| **[Evento](#evento)** agrupado em **issue** — `captureException` / `captureMessage` | Módulo **Issues** |
|
|
47
|
+
| **Monitor (cron)** — `withMonitor` / `checkIn` com `schedule` | Módulo **Monitores** |
|
|
48
|
+
| **[Transaction](#transaction) / spans** — `startTransaction` (e [`ctx.tx`](#transaction-de-run-ctxtx) dentro de uma run) | Performance no módulo **Agentes**; nas execuções, a aba de performance da solicitação |
|
|
49
|
+
| **Task / [run](#run)** — `register('task-slug', …)` casa com o `task_slug` do formulário | Módulo **Solicitações** (formulários em **Configurações → Formulários**) |
|
|
50
|
+
|
|
38
51
|
---
|
|
39
52
|
|
|
40
53
|
## Evento
|
|
41
54
|
|
|
42
|
-
Um **evento** é a foto de um instante que vale a pena registrar: uma exceção que estourou ou uma mensagem que você mandou. É a unidade básica
|
|
55
|
+
Um **evento** é a foto de um instante que vale a pena registrar: uma exceção que estourou ou uma mensagem que você mandou. É a unidade básica da telemetria.
|
|
43
56
|
|
|
44
57
|
Quando você chama `captureException` ou `captureMessage`, o SDK monta o evento com o que a exceção traz (tipo, mensagem, stack trace com os frames em ordem) e **anexa tudo que está no [scope](#scope)** naquele momento: tags, usuário, contexts, extras e a trilha de [breadcrumbs](#breadcrumb). Depois disso o evento vai para a [fila](#fila-flush-e-close) e é enviado em lote.
|
|
45
58
|
|
|
46
|
-
No servidor, eventos parecidos são agrupados numa **issue** —
|
|
59
|
+
No servidor, eventos parecidos são agrupados numa **issue** — o que você vê no módulo Issues do app. É por isso que 4.000 falhas do mesmo timeout não viram 4.000 linhas na sua tela. Quem decide o que é "parecido" é o [fingerprint](#fingerprint).
|
|
47
60
|
|
|
48
61
|
```js
|
|
49
62
|
Hobots.captureException(error);
|
|
@@ -207,7 +220,7 @@ Tamanho do buffer: [`maxBreadcrumbs`](./api-reference.md#initoptions).
|
|
|
207
220
|
|
|
208
221
|
Uma **transaction** é uma unidade de trabalho **nomeada** e **medida**: ela começa, termina, e o que fica registrado é quanto tempo levou. É a resposta para "quanto demora minha rotina de emissão?" — e, quando você adiciona [spans](#span), para "onde foram esses minutos?".
|
|
209
222
|
|
|
210
|
-
Enquanto o [evento](#evento) responde _o que quebrou_, a transaction responde _quanto tempo levou_. São os dois eixos
|
|
223
|
+
Enquanto o [evento](#evento) responde _o que quebrou_, a transaction responde _quanto tempo levou_. São os dois eixos da telemetria.
|
|
211
224
|
|
|
212
225
|
```js
|
|
213
226
|
const tx = Hobots.startTransaction('processar-lote', 'rpa.job');
|
|
@@ -226,7 +239,7 @@ Três coisas que valem saber:
|
|
|
226
239
|
|
|
227
240
|
O `status` default é `'ok'`; encadeáveis: `setStatus`, `setName`, `setTag`.
|
|
228
241
|
|
|
229
|
-
Dentro de um handler
|
|
242
|
+
Dentro de um handler de task você **não** cria transaction — já existe uma em [`ctx.tx`](#transaction-de-run-ctxtx), e o `startTransaction()` chamado lá dentro devolve exatamente ela.
|
|
230
243
|
|
|
231
244
|
## Span
|
|
232
245
|
|
|
@@ -249,7 +262,7 @@ O `op` é a categoria (útil para agrupar "todas as queries") e a `description`
|
|
|
249
262
|
|
|
250
263
|
## Transaction de run (ctx.tx)
|
|
251
264
|
|
|
252
|
-
Dentro de um handler
|
|
265
|
+
Dentro de um handler de task você **não precisa** criar uma transaction: o SDK já abriu uma para aquela execução e entregou em `ctx.tx`. Ela nasce quando o agente captura a run, é **correlacionada** à execução pelo `run_id`, recebe o status conforme o desfecho (`ok`, `error` ou `cancelled`) e é **finalizada automaticamente** quando o handler termina — você nunca chama `ctx.tx.finish()`.
|
|
253
266
|
|
|
254
267
|
O que sobra para você é a parte interessante: marcar as **etapas** do trabalho com [spans](#span). Cada `startChild` vira uma barra no waterfall da aba de performance daquela execução no app.
|
|
255
268
|
|
|
@@ -270,8 +283,8 @@ Hobots.register('processar-nfe', async (params, ctx) => {
|
|
|
270
283
|
|
|
271
284
|
Sem nenhum `startChild` a transaction ainda existe e ainda mede o tempo total da run — o waterfall só fica com uma barra. Cada span que você abre é uma resposta a mais para "onde foram os 4 minutos".
|
|
272
285
|
|
|
273
|
-
-
|
|
274
|
-
- `ctx.tx` **não respeita o `tracesSampleRate`** — toda run gera uma transaction. A amostragem vale para as transactions que **você** abre com `startTransaction()
|
|
286
|
+
- **`Hobots.startTransaction()` dentro de um handler devolve a própria `ctx.tx`.** Cada execução tem exatamente **uma** transaction: o SDK detecta o contexto da run e reutiliza a transaction dela em vez de criar uma segunda — os spans caem no mesmo waterfall. Fora de um handler, `startTransaction()` cria uma transaction nova, sem `run_id`.
|
|
287
|
+
- `ctx.tx` **não respeita o `tracesSampleRate`** — toda run gera uma transaction. A amostragem vale para as transactions que **você** abre com `startTransaction()` fora de uma run.
|
|
275
288
|
- O nome é `run:<task>` e o `op` é `hobots.task`, preenchidos pelo SDK.
|
|
276
289
|
|
|
277
290
|
## Amostragem (sampleRate e tracesSampleRate)
|
|
@@ -338,11 +351,13 @@ Dois detalhes:
|
|
|
338
351
|
|
|
339
352
|
O timer do heartbeat é `unref`'d — ele **não** segura o processo vivo.
|
|
340
353
|
|
|
354
|
+
Com `tasks: true`, o heartbeat é **opcional**: o próprio poll de tasks já marca a presença do agente no painel. Ele continua essencial para agentes só de telemetria.
|
|
355
|
+
|
|
341
356
|
## instanceId
|
|
342
357
|
|
|
343
358
|
O **`instanceId`** é a identidade da instância do robô: qual VM, qual container, qual máquina. É **obrigatório** no `init()` e deve ser **estável entre reinícios** (`vm-cliente-01`, `container-nfe-3`) — se você gerar um valor novo a cada boot, o app vê uma frota de robôs fantasmas em vez de um robô que reiniciou.
|
|
344
359
|
|
|
345
|
-
O que o torna especial é que ele é a identidade dos **dois** canais ao mesmo tempo: o [heartbeat](#heartbeat)
|
|
360
|
+
O que o torna especial é que ele é a identidade dos **dois** canais ao mesmo tempo: o [heartbeat](#heartbeat) e o agente de [tasks](./tasks.md) enviam o mesmo `instanceId`. O servidor correlaciona os dois, e o robô aparece como **um agente só** no módulo Agentes — sem nenhuma configuração extra.
|
|
346
361
|
|
|
347
362
|
## Release e environment
|
|
348
363
|
|
|
@@ -359,7 +374,7 @@ Servem a duas perguntas concretas:
|
|
|
359
374
|
|
|
360
375
|
Uma **run** (execução) é um pedido concreto de trabalho criado no app: alguém preencheu o formulário da task, ou uma automação disparou, e agora existe uma solicitação esperando um agente pegar.
|
|
361
376
|
|
|
362
|
-
É a unidade em volta da qual
|
|
377
|
+
É a unidade em volta da qual as [tasks](./tasks.md) inteiras giram — no app, cada run é uma solicitação no módulo **Solicitações**. O ciclo de vida no servidor:
|
|
363
378
|
|
|
364
379
|
```
|
|
365
380
|
pending → claimed → running → succeeded | failed | canceled
|
|
@@ -372,7 +387,7 @@ pending → claimed → running → succeeded | failed | canceled
|
|
|
372
387
|
|
|
373
388
|
O agente só transiciona para `running`, `succeeded` e `failed`. `pending` e `claimed` são do servidor; `canceled` vem de alguém cancelando no app.
|
|
374
389
|
|
|
375
|
-
Cada run carrega os **`params`** (o JSON validado do formulário) e chega ao seu código como o primeiro argumento do handler, junto de um [`RunContext`](./api-reference.md#
|
|
390
|
+
Cada run carrega os **`params`** (o JSON validado do formulário) e chega ao seu código como o primeiro argumento do handler, junto de um [`RunContext`](./api-reference.md#taskhandler--runcontext) com logs, sinal de cancelamento e a [transaction](#transaction-de-run-ctxtx).
|
|
376
391
|
|
|
377
392
|
## Claim
|
|
378
393
|
|
|
@@ -406,13 +421,13 @@ Devolve `true` se tudo saiu dentro do tempo e `false` se estourou. `false` **nã
|
|
|
406
421
|
|
|
407
422
|
### `close(timeoutMs?)` — "acabou, encerra"
|
|
408
423
|
|
|
409
|
-
Encerra tudo, **nesta ordem**: para o agente
|
|
424
|
+
Encerra tudo, **nesta ordem**: para o agente de tasks (aguardando as runs em execução) → para o heartbeat → faz o flush final e fecha o transport. É sempre a última linha do seu programa.
|
|
410
425
|
|
|
411
426
|
> **Atenção:** `close()` é **terminal e sem volta**. Depois dele, todo `captureException`, transaction, check-in ou heartbeat é **descartado** com um aviso no console — não existe `reopen()`. Se o programa precisar voltar a emitir telemetria, chame `Hobots.init()` de novo.
|
|
412
427
|
|
|
413
|
-
> **Atenção:** o `timeoutMs` do `close()` é aplicado **duas vezes, em sequência** — uma para esperar as runs
|
|
428
|
+
> **Atenção:** o `timeoutMs` do `close()` é aplicado **duas vezes, em sequência** — uma para esperar as runs de tasks, outra para o flush final. `close(15_000)` pode levar até ~30s no pior caso. Se você tem um SIGTERM com prazo curto (Kubernetes, systemd), dimensione por aí.
|
|
414
429
|
|
|
415
|
-
O `flush` cobre a fila
|
|
430
|
+
O `flush` cobre a fila da **telemetria**. Os logs de uma run de task (`ctx.log`) são um canal separado, com o próprio ritmo — quem espera por eles é o `close()`/`stop()`, ao aguardar a run terminar.
|
|
416
431
|
|
|
417
432
|
Defaults e tempos dos dois: [Tempos e intervalos](./api-reference.md#tempos-e-intervalos).
|
|
418
433
|
|