# Snapshots

Os content servers irão periodicamente compilar resumos das entidades ativas que estão hospedando, chamados *snapshots*. Eles são arquivos regulares [files](https://github.com/decentraland/docs/blob/main/contributor/filesystem.md) e podem ser baixados usando seu identificador.

Snapshots são criados diariamente, semanalmente, mensalmente e anualmente. Cada um contém o conjunto de entidades ativas que mudaram desde o snapshot anterior para esse intervalo.

Snapshots conterão versões conflitantes das mesmas entidades (ou seja, diferentes [manifest files](https://github.com/decentraland/docs/blob/main/contributor/entities.md#properties) associados ao mesmo pointer) conforme são atualizados. Ao examiná-los, os clientes devem manter a versão presente no snapshot mais recente. Como os content servers podem excluir arquivos inativos, versões antigas de entidades não são garantidas para download.

Quando um novo snapshot *replaces* os mais antigos (por exemplo, um snapshot semanal que combina uma série de diários), seus metadados indicam quais arquivos anteriores são substituídos para que os clientes não precisem baixá-los.

O conjunto completo de entidades ativas pode ser descoberto combinando todos os snapshots disponíveis (mais abaixo há mais detalhes), mantendo a entidade mais recente referenciada por cada [pointer](https://github.com/decentraland/docs/blob/main/contributor/pointers.md) descoberto ao longo do caminho.

Você pode experimentar com snapshots usando código funcional na [practice](https://github.com/decentraland/docs/blob/main/contributor/practice.md) seção.

### Descobrindo Snapshots <a href="#discover" id="discover"></a>

Para localizar o conjunto atual de snapshots, use o [`snapshots` endpoint](https://decentraland.github.io/catalyst-api-specs/#tag/Content-Server/operation/getSnapshots). A resposta contém um array de itens com estes campos:

| Campo                     | Valor                                                                                        |
| ------------------------- | -------------------------------------------------------------------------------------------- |
| `generationTimestamp`     | O timestamp Unix UTC quando este snapshot foi criado.                                        |
| `hash`                    | O snapshot [file](https://github.com/decentraland/docs/blob/main/contributor/filesystem.md). |
| `numberOfEntities`        | O número de entradas no arquivo de snapshot.                                                 |
| `replacedSnapshotHashes`  | Um array com os `hash` de quaisquer snapshots substituídos por este.                         |
| `timeRange.initTimestamp` | O timestamp Unix UTC (em milissegundos) para o início do intervalo do snapshot.              |
| `timerange.endTimestamp`  | O timestamp Unix UTC (em milissegundos) para o fim do intervalo do snapshot.                 |

Por exemplo:

```json
{
  "generationTimestamp": 1684979298844,
  "hash": "bafybeiflmm46nr4vv2h3wuzbx3pukcz7ju4fhbfzt6yxmoo533uktlgru4",
  "numberOfEntities": 12345,
  "replacedSnapshotHashes": [ "bafybeicw6x75ieaxfwynekbyhpcsgctpjkt6cb4j6oa7s57qjj6e4b5phd" ],
  "timeRange": {
     "initTimestamp": 1684281600000,
     "endTimestamp": 1684886400000
  }
}
```

### Baixando Snapshots <a href="#download" id="download"></a>

Usando o `hash` campo de um snapshot, os clientes podem baixar o associado contendo entidades criadas ou atualizadas nesse intervalo de tempo.

Os arquivos de snapshot começam com esta linha exata:

```
### Decentraland json snapshot
```

Depois disso, cada linha é um documento JSON descrevendo uma [entity](https://github.com/decentraland/docs/blob/main/contributor/entities.md) com os seguintes campos:

| Campo             | Valor                                                                                                                                                    |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entityId`        | O identificador imutável para esta [entity](https://github.com/decentraland/docs/blob/main/contributor/entities.md).                                     |
| `entityType`      | Um de `cena`, `perfil`, `wearable`, `emote`, `store` ou `outfits`.                                                                                       |
| `pointers`        | Um array de [pointers](https://github.com/decentraland/docs/blob/main/contributor/pointers.md) que resolvem (ou costumavam resolver) para esta entidade. |
| `entityTimestamp` | O timestamp Unix UTC (em milissegundos) quando esta entidade foi enviada.                                                                                |
| `authChain`       | O [auth\_chain](https://github.com/decentraland/docs/blob/main/contributor/entities.md#ownership) para esta entidade.                                    |

Uma entrada típica se parece com isto:

```json
{
  "entityId": "bafkreigrvaqynmiglpvewwhn2yd63q5dvagrrt5jbhimzvbrn5kimj5zne",
  "entityType": "wearable",
  "pointers": ["urn:decentraland:matic:collections-v2:0x11a6879861f36cbad632a4e7226816a16139fb33:0"],
  "entityTimestamp": 1671117456129,
  "authChain": [
    // ... authentication chain payloads and signatures
  ]
}
```

{% hint style="info" %}
Se você pretende analisar um snapshot linha por linha, lembre-se de pular (ou, melhor ainda, validar) a primeira com o cabeçalho, e esteja pronto para lidar com uma linha vazia no final do arquivo.
{% endhint %}

#### Iniciando um Índice de Entidades <a href="#index-start" id="index-start"></a>

Clientes que queiram indexar o conjunto inteiro de entidades ativas devem processar todos os snapshots atualmente disponíveis, e manter a mais recente [entity](https://github.com/decentraland/docs/blob/main/contributor/entities.md) para cada [pointer](https://github.com/decentraland/docs/blob/main/contributor/pointers.md).

A estratégia mais simples é processar os snapshots em ordem reversa cronológica (ou seja, do mais recente para o mais antigo), ignorando pointers que já foram descobertos, a fim de manter a referência para a entidade mais recente.

Em pseudo-código:

```py
# Baixe o conjunto atual de snapshots e ordene-os do mais novo ao mais antigo:
snapshots = get_snapshots()
snapshots.sort('timeRange.initTimestamp', DESCENDING)

seen_pointers = set()

# Processe os snapshots, mantendo a entidade mais nova para cada pointer:
for snapshot in snapshots:
    items = get_snapshot_items(snapshot) 

    for item in items:
        if any(pointer in seen_pointers for pointer in item.pointers):
            discard(item)
        else:
            keep(item)
            seen_pointers.update(item.pointers)
```

Como entidades individuais podem ser referenciadas por múltiplos pointers (como é comum com [cenas](https://docs.decentraland.org/contributor/contributor-pt/content/entity-types/scenes)), todos eles devem ser verificados antes de decidir manter ou descartar o item.

{% hint style="info" %}
Os arquivos de snapshot para os intervalos de tempo maiores podem ser muito grandes. Para propósitos de desenvolvimento e experimentação que não exigem indexar o conjunto inteiro de entidades, é recomendável usar os snapshots menores. O conjunto resultante de entidades será incompleto, mas válido.
{% endhint %}

#### Atualizando um Índice de Entidades <a href="#index-update" id="index-update"></a>

Clientes que mantêm um índice de entidades atualizado podem fazer chamadas periódicas ao [`snapshots`](https://decentraland.github.io/catalyst-api-specs/#tag/Content-Server/operation/getSnapshots) endpoint, e determinar se devem baixar cada arquivo considerando:

* O snapshot identificado por `hash` já foi baixado?
* Está `hash` na `replacedSnapshotHashes` lista de outro snapshot que já foi baixado?
* O `timeRange` é relevante para os propósitos atuais?

Se quaisquer novos snapshots precisarem ser processados, a mesma estratégia acima pode ser usada para atualizar um conjunto de dados existente.

### Exemplos

Na [practice](https://github.com/decentraland/docs/blob/main/contributor/practice.md) seção, você encontrará exemplos de código que funcionam com o sistema de snapshots.
