El «backfilling» es el proceso de recuperar datos históricos de la cadena de bloques para alimentar bases de datos, analizar tendencias pasadas o auditar transacciones. Tanto si necesitas indexar una cadena completa desde el bloque Génesis como si solo quieres ponerte al día con la actividad de las últimas 24 horas, la recuperación eficiente de datos históricos supone un reto fundamental para la infraestructura.
Streams facilitan el rellenado de datos históricos gracias a plantillas de un solo clic, filtrado del lado del servidor, opciones de procesamiento por lotes y compresión, y entrega garantizada a tu destino preferido. En lugar de escribir scripts complejos para sondear puntos finales RPC, basta con configurar un Stream, establecer el rango de bloques y, si se desea, aplicar filtros para extraer solo los datos que necesitas; así, Streams los datos a tu destino (por ejemplo, Webhook, S3, PostgreSQL, Azure Storage, etc.) de forma fiable y a gran escala.
¿Por qué utilizar Streams el relleno?
Streams los aspectos relacionados con la infraestructura, como los reintentos, la ordenación de bloques y la gestión de errores, lo que te permite centrarte exclusivamente en la lógica de datos de tu aplicación.
| Característica | Descripción |
|---|---|
| Filtros | Puedes procesar y transformar los datos en el servidor antes de su envío mediante filtros. Utiliza decodificar recibos EVM para la decodificación hexadecimal, la creación de cargas útiles personalizadas y la depuración con console.log(). |
| Agrupación y compresión | Puedes configurar tamaño_del_lote_del_conjunto_de_datos (p. ej., 10-100) para agrupar varios bloques por solicitud. También puedes activar compresión: «gzip» en configuración de destino. |
| Almacén de clave-valor | Puedes guardar listas de seguimiento, ABI, o valores de configuración, y acceder a ellos en los filtros mediante qnLib métodos. También puedes gestionar los valores a través de la API REST. |
| API REST | Puedes crear, actualizar, pausar y eliminar Streams mediante programación Streams la API REST. |
| Multicadena | Cada «Stream» está destinado a una cadena o red concreta. Puedes ejecutar varios Streams paralelo para realizar rellenos en múltiples cadenas. Consulta «Cadenas compatibles». |
| Transición en tiempo real | Puedes omitir fin_rango para continuar con la transmisión una vez finalizada la recuperación de datos. Puedes utilizar elastic_batch_enabled para reducir automáticamente el tamaño del lote en la punta y mantener_distancia_respecto_a_la_punta para reducir reorganización frecuencia. |
Estimación de los costes de relleno
La recuperación de datos históricos de la cadena de bloques consume créditos de API en función del número de bloques procesados, aplicando los multiplicadores del conjunto de datos de red. Streams el mismo fondo común de créditos de API que RPC.
Utiliza la calculadora de créditos de la API para calcular los costes de relleno antes de empezar. La calculadora muestra:
- Total de créditos API necesarios para completar los bloques históricos disponibles
- Créditos por bloque en función del conjunto de datos y la red seleccionados
- ¿Qué redes admiten el «backfilling»? (Solana , por ejemplo, no admiten actualmente el «backfilling»).
Cómo rellenar datos
-
Selecciona tu cadena y tu red. Consulta las cadenas compatibles con Streams.
-
Define el rango de bloques. Puedes elegir si quieres empezar desde el bloque Génesis o desde una altura de bloque concreta. En cuanto al bloque final, puedes establecerlo en una altura concreta o elegir la transmisión continua para seguir recibiendo nuevos bloques.
-
Selecciona tu conjunto de datos. Streams diferentes conjuntos de datos, como «Block», «Block con recibos», «Transacciones», «Registros», etc. Elige el que mejor se adapte a tu caso de uso. Consulta la sección «Datos retrospectivos por ecosistema» más abajo para ver los conjuntos de datos específicos de cada cadena.
-
Aplica filtros (opcional). Utiliza el filtrado del lado del servidor para limitar los datos que deseas recibir.
-
Elige tu destino. Configura dónde quieres que se envíen los datos, como Webhooks, S3, PostgreSQL, etc. Consulta la documentación sobre destinos para obtener más detalles.
-
Comprueba la conexión y envía una carga de prueba en la página de configuración de Stream para asegurarte de que todo está configurado correctamente.
-
Inicia la retransmisión.
Consulta nuestros «Consejos para el relleno» a continuación para obtener recomendaciones sobre la preparación de lotes, la compresión y la optimización del rendimiento.
Datos de relleno por ecosistema
Streams utilizar para completar datos de cualquier ecosistema, incluidos Ethereum, Bitcoin, Solana y otros. Dado que tienen estructuras y formatos de datos diferentes, selecciona tu ecosistema a continuación para ver conjuntos de datos específicos de cada cadena, filtros de ejemplo y respuestas.
- Ethereum las cadenas EVM
- Solana
- Bitcoin
- XRP Ledger
Ethereum las cadenas EVM
Streams numerosas cadenas EVM, entre las que se incluyen Ethereum, Base, Arbitrum y BNB Smart Chain. Todas las cadenas EVM comparten una arquitectura y una estructura de datos similares, por lo que los filtros y los formatos de carga útil suelen ser los mismos en todas las cadenas, aunque pueden existir algunas diferencias específicas de cada cadena.
Descodificación de datos del EVM
Al trabajar con cadenas compatibles con EVM, puedes verificar y analizar los datos más fácilmente utilizando el decodificar recibos EVM función. Esta utilidad transforma datos hexadecimales sin procesar en formatos legibles para el usuario, utilizando como entradas los recibos de transacción sin procesar y las ABI de tus contratos.
El proceso de decodificación realiza automáticamente lo siguiente:
- Compara las firmas de eventos de los registros de transacciones con las ABI facilitadas.
- Decodifica los parámetros según su tipo (direcciones, números enteros, cadenas, etc.).
- Devuelve datos estructurados con parámetros con nombre en un
registros descodificadosobjeto.
Más información sobre esta función: Decodificación de datos EVM
Fuentes de datos disponibles
En el caso de cadenas EVM como Ethereum, Base, Arbitrum y BNB Smart Chain, puedes utilizar los siguientes conjuntos de datos para completar los datos históricos.
Para consultar la especificación JSON completa y los detalles de cada conjunto de datos, consulta la documentación sobre fuentes de datos.
| Fuente de datos | Descripción |
|---|---|
| Bloque | Una matriz de objetos de bloque, tal y como la devuelve la función eth_getBlockByNumber |
| Bloc de recibos | Una matriz de objetos que contiene un conjunto de datos compuesto por bloques y recibos, tal y como los devuelven las funciones `eth_getBlockByNumber` y `eth_getBlockReceipts`. |
| Transacciones | Una matriz de matrices de objetos de transacción, tal y como aparecen en la matriz de transacciones de los datos del bloque |
| Registros | Una matriz de matrices de objetos de registro, tal y como aparecen dentro de la matriz «logs» en los recibos de transacciones. |
| Recibos | Una matriz de matrices, cada una de las cuales contiene objetos de recibo tal y como los devuelve la función `eth_getBlockReceipts`. |
| Rastros (debug_trace) | Una matriz de matrices de datos de seguimiento, tal y como los devuelve la función `debug_traceBlock`. |
| Trazas (trace_block) | Una matriz de matrices de datos de seguimiento, tal y como los devuelve la función `trace_block` |
| Bloque con recibos + debug_trace | Una matriz de objetos que contiene un conjunto de datos compuesto por bloques, recibos y trazas de `debug_traceBlock` |
| Bloque con recibos + trace_block | Una matriz de objetos que contiene un conjunto de datos compuesto por bloques, recibos y trazas procedentes de trace_block |
La disponibilidad de las fuentes de datos varía según la cadena. Es posible que algunos conjuntos de datos (concretamente, Traces) no sean compatibles con todas las redes EVM. Consulta la página «Fuentes de datos» para ver la matriz de compatibilidad actual.
Ejemplo: Transferencias de tokens ERC-20
La función de ejemplo que se muestra a continuación filtra un bloque de transacciones para identificar y descodificar las transferencias de tokens ERC-20 estándar, comprobando los datos de entrada en busca de los transferencia firma del método.
- Ir
- JavaScript
- Respuesta
// Chain: Ethereum
// Dataset: Transactions
// Test with block: 23977403
type Payload struct {
Data [][]Tx `json:"data"`
Metadata map[string]interface{} `json:"metadata"`
}
type Tx struct {
Hash string `json:"hash"`
From string `json:"from"`
To string `json:"to"`
Input string `json:"input"`
BlockNumber string `json:"blockNumber"`
}
func Filter(qn *qn.QNContext, payload Payload) interface{} {
// The standard ERC-20 transfer(address,uint256) method signature
const transferMethodID = "0xa9059cbb"
var filteredTransactions []map[string]interface{}
// Loop through all blocks in the batch (data is [][]tx: outer = block, inner = txs)
for _, transactions := range payload.Data {
for _, tx := range transactions {
// Ensure the input carries a full transfer(address,uint256) call:
// "0x" + 4-byte selector + two 32-byte words = 138 hex chars.
if !strings.HasPrefix(tx.Input, transferMethodID) || len(tx.Input) < 138 {
continue
}
// Decode the 'to' address (skip selector + left-padding)
toAddress := "0x" + tx.Input[34:74]
// Decode the 'value' (amount) from the trailing 32-byte word.
// uint256 can exceed int64, so convert hex → decimal without math/big.
amount := hexToDecimal(tx.Input[74:])
filteredTransactions = append(filteredTransactions, map[string]interface{}{
"txHash": tx.Hash,
"fromAddress": tx.From,
"toAddress": toAddress,
"amount": amount,
"tokenContract": tx.To,
"blockNumber": tx.BlockNumber,
})
}
}
// Return nil if no transfers were found — skips delivery to your destination
// (API credits are still consumed based on blocks processed).
if len(filteredTransactions) == 0 {
return nil
}
return map[string]interface{}{"transactions": filteredTransactions}
}
// hexToDecimal converts an arbitrary-length hex string (with or without a "0x"
// prefix) to its decimal string form, safe for full uint256 values.
func hexToDecimal(hexStr string) string {
hexStr = strings.TrimPrefix(strings.ToLower(hexStr), "0x")
hexStr = strings.TrimLeft(hexStr, "0")
if hexStr == "" {
return "0"
}
// digits holds the decimal value little-endian (least-significant first).
digits := []int{0}
for _, c := range hexStr {
v, err := strconv.ParseInt(string(c), 16, 32)
if err != nil {
return "0"
}
carry := int(v)
for i := 0; i < len(digits); i++ {
cur := digits[i]*16 + carry
digits[i] = cur % 10
carry = cur / 10
}
for carry > 0 {
digits = append(digits, carry%10)
carry /= 10
}
}
var sb strings.Builder
for i := len(digits) - 1; i >= 0; i-- {
sb.WriteByte(byte('0' + digits[i]))
}
return sb.String()
}
// Chain: Ethereum
// Dataset: Transactions
// Test with block: 23977403
function main(payload) {
const filteredTransactions = [];
// The standard ERC-20 transfer(address,uint256) method signature
const transferMethodId = "0xa9059cbb";
// Loop through all blocks in the batch
for (const transactions of payload.data) {
for (const transaction of transactions) {
// Ensure the transaction object and input data are valid
if (typeof transaction === 'object' && transaction !== null && typeof transaction.input === 'string') {
// Check if the transaction input starts with the transfer method ID
if (transaction.input.startsWith(transferMethodId)) {
// Decode the 'to' address (skipping method ID and padding)
const toAddress = "0x" + transaction.input.substr(34, 40);
// Decode the 'value' (amount) from the subsequent hex data
const value = BigInt("0x" + transaction.input.substr(74));
filteredTransactions.push({
txHash: transaction.hash,
fromAddress: transaction.from,
toAddress: toAddress,
amount: value.toString(),
tokenContract: transaction.to,
blockNumber: transaction.blockNumber,
});
}
}
}
}
// Return the filtered list, or null if no transfers were found (skips delivery to your destination; API credits are still consumed based on blocks processed)
return filteredTransactions.length > 0 ? { transactions: filteredTransactions } : null;
}
{
"transactions": [
{
"amount": "80007920",
"blockNumber": "0x16dddbb",
"fromAddress": "0xa80f9793051cd1f428ad61b276d431f30dd59b6a",
"toAddress": "0xabd22d07c199a56bafa5e2add3cde1127bc98292",
"tokenContract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"txHash": "0x013a9cdd1de2ade97a1d79178fe59f2025e41495db050aab0cc706cd2be3b2fe"
},
{
"amount": "71839000",
"blockNumber": "0x16dddbb",
"fromAddress": "0x828ee64b59f33e6c3a6b8d4ad8298aeb65421445",
"toAddress": "0xbb03a0b5159d985c304ab183b80e884ae38c9c89",
"tokenContract": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"txHash": "0x2ae18c8918de4744df1d93729e75f89f402723630982224654d18cae047ec74b"
}
]
}
Recursos adicionales
Solana
Streams completar retrospectivamente rangos de slots históricos en Solana. Debido al elevado rendimiento de la red y al enorme volumen de datos, estas completaciones retrospectivas suelen utilizarse para indexar intervalos de tiempo específicos (por ejemplo, recuperar los datos de las últimas 1-2 semanas) en lugar de todo el historial del libro mayor desde Génesis.
Para consultar la especificación JSON completa y los detalles de cada conjunto de datos, consulta la documentación sobre fuentes de datos.
Las cuentas de prueba gratuitas solo pueden crear Solana Streams sigan la punta de la cadena de bloques en tiempo real. Los datos históricos deStreams Solana Streams soloStreams disponibles en los planes de pago.
Fuentes de datos disponibles
| Fuente de datos | Descripción |
|---|---|
| Bloque | Una matriz de objetos «block» tal y como la devuelve la función getBlock |
| Programas + Registros | Una matriz de objetos que contiene mensajes de registro y metadatos de transacciones relacionados con las invocaciones del programa |
Ejemplo: Seguimiento de las variaciones en el saldo de una cuenta
La función de ejemplo que se muestra a continuación filtra un bloque en busca de transacciones completadas con éxito en las que participe una Solana específica Solana y calcula la variación del saldo de SOL (delta) para esa cuenta en cada transacción.
- Ir
- JavaScript
- Respuesta
// Chain: Solana
// Dataset: Block
// Test with slot: 282164688
type Payload struct {
Data []SolanaBlock `json:"data"`
Metadata map[string]interface{} `json:"metadata"`
}
type SolanaBlock struct {
ParentSlot int64 `json:"parentSlot"`
BlockTime int64 `json:"blockTime"`
Transactions []SolanaTx `json:"transactions"`
}
// Only the fields the filter reads are declared, so heavy fields such as
// logMessages are never decoded.
type SolanaTx struct {
Meta struct {
Err interface{} `json:"err"`
PreBalances []int64 `json:"preBalances"`
PostBalances []int64 `json:"postBalances"`
} `json:"meta"`
Transaction struct {
Signatures []string `json:"signatures"`
Message struct {
AccountKeys []struct {
Pubkey string `json:"pubkey"`
} `json:"accountKeys"`
} `json:"message"`
} `json:"transaction"`
}
func Filter(qn *qn.QNContext, payload Payload) interface{} {
// Configuration: the target account and filtering preferences.
const (
// The public key of the account to track (e.g. a specific wallet or program)
accountID = "9kwU8PYhsmRfgS3nwnzT3TvnDeuvdbMAXqWsri2X8rAU"
// Set to true to ignore failed transactions (recommended to reduce noise)
skipFailed = true
)
var matchedTransactions []map[string]interface{}
// Loop through all blocks in the batch
for _, block := range payload.Data {
for _, tx := range block.Transactions {
// 1. Skip failed transactions if configured to do so
if skipFailed && tx.Meta.Err != nil {
continue
}
// 2. Find the index of our target account within the account keys
accountIndex := -1
for i, account := range tx.Transaction.Message.AccountKeys {
if account.Pubkey == accountID {
accountIndex = i
break
}
}
// If the target account is not involved in this transaction, skip it
if accountIndex == -1 {
continue
}
// Guard against malformed balance arrays
if accountIndex >= len(tx.Meta.PreBalances) || accountIndex >= len(tx.Meta.PostBalances) {
continue
}
// 3. Retrieve balance information using the account index
preBalance := tx.Meta.PreBalances[accountIndex]
postBalance := tx.Meta.PostBalances[accountIndex]
delta := postBalance - preBalance
// 4. Skip transactions where the account's balance did not change
if delta == 0 {
continue
}
var signature string
if len(tx.Transaction.Signatures) > 0 {
signature = tx.Transaction.Signatures[0]
}
// 5. Construct and append the custom payload
matchedTransactions = append(matchedTransactions, map[string]interface{}{
"signature": signature,
"slot": block.ParentSlot + 1,
"blockTime": block.BlockTime,
"accountKey": accountID,
"preBalance": preBalance,
"postBalance": postBalance,
"delta": delta,
})
}
}
if len(matchedTransactions) == 0 {
return nil // skip delivery
}
return map[string]interface{}{"matchedTransactions": matchedTransactions}
}
// Chain: Solana
// Dataset: Block
// Test with slot: 282164688
// Configuration: Define the target account and filtering preferences
const FILTER_CONFIG = {
// The Public Key of the account to track (e.g., a specific wallet or program)
accountId: '9kwU8PYhsmRfgS3nwnzT3TvnDeuvdbMAXqWsri2X8rAU',
// Set to true to ignore failed transactions (recommended to reduce noise)
skipFailed: true,
};
function main(payload) {
const matchedTransactions = [];
// Loop through all blocks in the batch
for (const block of payload.data) {
for (const tx of block.transactions) {
const result = processTransaction(tx, block);
if (result) {
matchedTransactions.push(result);
}
}
}
return matchedTransactions.length > 0 ? { matchedTransactions } : null;
}
// Helper function to process individual transactions
function processTransaction(transactionWithMeta, block) {
const { meta, transaction } = transactionWithMeta;
// 1. Skip failed transactions if configured to do so
if (FILTER_CONFIG.skipFailed && meta.err !== null) {
return null;
}
// 2. Find the index of our target account within the transaction's account keys
const accountIndex = transaction.message.accountKeys.findIndex(
account => account.pubkey === FILTER_CONFIG.accountId
);
// If the target account is not involved in this transaction, skip it
if (accountIndex === -1) {
return null;
}
// 3. Retrieve balance information using the account index
const preBalance = meta.preBalances[accountIndex];
const postBalance = meta.postBalances[accountIndex];
const delta = postBalance - preBalance;
// 4. Skip transactions where the account's balance did not change
if (delta === 0) {
return null;
}
// 5. Construct and return the custom payload
return {
signature: transaction.signatures[0],
slot: block.parentSlot + 1,
blockTime: block.blockTime,
accountKey: FILTER_CONFIG.accountId,
preBalance,
postBalance,
delta,
};
}
{
"matchedTransactions": [
{
"accountKey": "9kwU8PYhsmRfgS3nwnzT3TvnDeuvdbMAXqWsri2X8rAU",
"blockTime": 1723055487,
"delta": -25000000000000,
"postBalance": 485830395323,
"preBalance": 25485830395323,
"signature": "2nWu9XYxKHWNiwGDHLnHYqrF3uGZCN5subE3rbuFqnxwoGQ11FxSEoz6CffmssYhqC43ewDyhiAhvPZNMSzbqVMC",
"slot": 282164688
}
]
}
Recursos adicionales
- Guía técnica: Cómo completar los datos Solana
Bitcoin
Streams el rellenado retrospectivo para Bitcoin Bitcoin . Estas cadenas utilizan el modelo UTXO (salida de transacción no gastada), que difiere de las cadenas de bloques basadas en cuentas.
Para consultar la especificación JSON completa y los detalles de cada conjunto de datos, consulta la documentación sobre fuentes de datos.
Fuentes de datos disponibles
| Fuente de datos | Descripción |
|---|---|
| Bloque | Una matriz de objetos tal y como la devuelve la función bb_getBlock de Blockbook |
Ejemplo: Seguimiento de transacciones de alto valor
La función de ejemplo que se muestra a continuación filtra el flujo para realizar un seguimiento de la actividad de las «ballenas», identificando y devolviendo únicamente las transacciones con un valor igual o superior a 1 BTC.
- Función de filtro
- Respuesta
// Chain: Bitcoin
// Dataset: Block
// Test with block: 927171
function main(payload) {
const {
data,
metadata,
} = payload;
// Define the threshold: 1 BTC in Satoshis (100,000,000 sats = 1 BTC)
const MIN_VALUE = 100000000;
const results = [];
// Iterate through each block in the batch (Streams may deliver multiple blocks at once)
for (const block of data) {
// Iterate through all transactions in the current block
for (const tx of block.txs) {
// Filter logic: Check if the transaction value meets our threshold
if (parseInt(tx.value) >= MIN_VALUE) {
// Construct a simplified custom payload with only relevant details
results.push({
txid: tx.txid,
blockHeight: tx.blockHeight,
blockTime: tx.blockTime,
// Convert Satoshis to BTC for human readability
valueBTC: parseInt(tx.value) / 100000000,
fees: tx.fees
});
}
}
}
// Return the array of high-value transactions, or null to skip the block if none found
return results.length ? results : null;
}
[
{
"blockHeight": 927171,
"blockTime": 1765316511,
"fees": "0",
"txid": "fbc62d0e65f2bed9e193480b33adc6f117ba44c839928becadfb61f817f6e7fb",
"valueBTC": 3.14554746
},
{
"blockHeight": 927171,
"blockTime": 1765316511,
"fees": "5640",
"txid": "494ff35569b01a799db0ef0975923844faa46bd1a57a8625cd44b152ded3b661",
"valueBTC": 6.92443529
}
]
XRP Ledger
Streams te Streams recuperar datos históricos del XRP Ledger XRPL) y enviar objetos completos del libro mayor a tu destino.
Para consultar la especificación JSON completa y los detalles de cada conjunto de datos, consulta la documentación sobre fuentes de datos.
Fuentes de datos disponibles
| Fuente de datos | Descripción |
|---|---|
| Libro mayor | Un array de objetos «ledger» tal y como lo devuelve la función «ledger» |
Ejemplo: Filtrar pagos realizados con éxito
La función de ejemplo que se muestra a continuación filtra el flujo para conservar únicamente las transacciones de pago realizadas con éxito, descartando otros tipos de transacciones y los intentos fallidos, con el fin de garantizar un conjunto de datos limpio de transferencias de valor.
- Función de filtro
- Respuesta
// Chain: XRP Ledger
// Dataset: Ledger
// Test with ledger: 100768299
function main(payload) {
const results = [];
const {
data,
metadata,
} = payload;
// Iterate through each ledger in the batch (Streams may deliver multiple ledgers at once)
for (const item of data) {
const ledger = item.ledger;
// Loop through all transactions in the current ledger
for (const tx of ledger.transactions) {
// Filter Logic:
// 1. Check if it is a 'Payment' type (standard value transfer)
// 2. Check if the transaction succeeded ('tesSUCCESS')
if (
tx.TransactionType === "Payment" &&
tx.metaData?.TransactionResult === "tesSUCCESS"
) {
// Construct a simplified custom payload with key transfer details
results.push({
hash: tx.hash,
ledgerIndex: ledger.ledger_index,
closeTime: ledger.close_time_iso, // Human-readable timestamp
account: tx.Account, // Sender
destination: tx.Destination, // Receiver
fee: tx.Fee
});
}
}
}
// Return the filtered results, or null to skip the ledger if no payments were found
return results.length ? results : null;
}
[
{
"account": "rUg8ac5ikpTaWk5RPei8xuYkNEyUs53G1i",
"closeTime": "2025-12-09T21:49:31Z",
"destination": "rNxp4h8apvRis6mJf9Sh8C6iRxfrDWN7AV",
"fee": "12",
"hash": "0059A19205DA30084FB42C54C343BED150D8F3EB5443FA2C77B87F540A17D6D7",
"ledgerIndex": "100768299"
},
{
"account": "rUg8ac5ikpTaWk5RPei8xuYkNEyUs53G1i",
"closeTime": "2025-12-09T21:49:31Z",
"destination": "rMqfygR9sbZvWMRqStzUunBXH8Ut5DLfxs",
"fee": "12",
"hash": "099243DEE9C12B90A6080A99FC10EB620CDBB713BF17CC6E5D674176A4308A0A",
"ledgerIndex": "100768299"
}
]
Consejos para el relleno
Organización por lotes para un relleno más rápido
De forma predeterminada, Streams un bloque cada vez. En el caso de las actualizaciones retrospectivas, aumentar el tamaño del lote (por ejemplo, 10 o 100 bloques por envío) reduce la sobrecarga y acelera la ingesta. Ajusta esta configuración en los parámetros de Stream en función de la capacidad de tu destino.
Si vas a seguir con la transmisión en tiempo real, te recomendamos que utilices Elastic Batch para ajustar automáticamente el tamaño de los lotes.
Optimización del rendimiento
La combinación del filtrado (para transmitir únicamente los datos que se desean) con la compresión (para optimizar la transferencia de datos) mejora el rendimiento durante las recargas a gran escala.
Si tu filtro devuelve null, no se envían datos a tu destino (lo que reduce las cargas útiles innecesarias). Nota: Streams créditos de API en función de los bloques procesados, independientemente del filtrado.
Filtros de depuración
Registra la información de tu función de filtro para depurar durante el desarrollo. Los registros aparecen en la pestaña «Registros», junto a la pestaña «Resultados», en el Editor de filtros de flujo.
En JavaScript, utiliza console.log(). En Go, utiliza fmt.Println — su salida se recoge en el Registros La pestaña «tab» funciona como un registro de nivel informativo y formatea automáticamente los objetos (mapas, segmentos, estructuras) en una cadena de caracteres, lo que te permite registrar la carga útil directamente.
El ejemplo de Go que aparece a continuación parte de la base de que Carga útil La estructura se declara en tu filtro (véanse los ejemplos anteriores). Al hacer referencia a un tipo no definido en el Filtro La firma hace que el intérprete genere un mensaje engañoso bucle de definición de constantes error, así que asegúrate de que la estructura esté definida.
- Ir
- JavaScript
func Filter(qn *qn.QNContext, payload Payload) interface{} {
fmt.Println("Data:", payload.Data)
fmt.Println("Metadata:", payload.Metadata)
// ... rest of your filter
}
function main(payload) {
const {
data,
metadata,
} = payload;
console.log("Data:", data)
console.log("Metadata:", metadata)
// ... rest of your filter
}
Pruebas con datos sin procesar
Al crear un nuevo filtro, puedes descargar los datos sin procesar de un bloque de prueba concreto desde la interfaz de usuario de configuración de Stream. Esto te ayuda a comprender la estructura exacta de la carga útil antes de escribir la lógica del filtro.
Seguridad y autenticación
Streams un token de seguridad con cada entrega que puedes utilizar para verificar las solicitudes procedentes de Quicknode. También puedes configurar encabezados personalizados en los ajustes de tu destino. Para los destinos de webhook, consulta «Cómo validar los mensajes Streams entrantes Streams » para obtener más detalles sobre la implementación.
Recursos relacionados
- Plantillas de páginas de productos y de rellenado: Streams de Quicknode Streams
- Tutorial en vídeo: Relleno de datos en la cadena de bloques
- Documentación: Streams
- Documentación: Fuentes de datos
- Documentación: Destinos
- Documentación: Filtros
- Documentación: Almacén de pares clave-valor
- Guías técnicas: Streams de todas Streams
- Relleno para empresas: Ponte en contacto con el departamento de ventas para obtener asistencia especializada y una solución a medida para trabajos de relleno a gran escala.