Skip to content

Instantly share code, notes, and snippets.

@gunzip
Last active March 17, 2025 09:56
Show Gist options
  • Save gunzip/483263aadb51df672902d200fdc0eadc to your computer and use it in GitHub Desktop.
Save gunzip/483263aadb51df672902d200fdc0eadc to your computer and use it in GitHub Desktop.
Trial System Alternative
/*
* Caricament da csv semplice
*/
import { CosmosClient } from "@azure/cosmos";
import * as fs from "fs";
import { parse } from "csv-parse";
// Configurazione di Cosmos DB
const endpoint = "TUO_ENDPOINT_COSMOS_DB"; // Es: https://<tuo-account>.documents.azure.com:443/
const key = "TUA_CHIAVE_PRIMARIA";
const databaseId = "TUO_DATABASE";
const containerId = "TUO_CONTAINER";
const client = new CosmosClient({ endpoint, key });
const database = client.database(databaseId);
const container = database.container(containerId);
// Funzione per caricare il CSV
async function uploadCsvToCosmos(csvFilePath: string) {
const parser = fs
.createReadStream(csvFilePath)
.pipe(parse({ columns: true, trim: true })); // Parsa il CSV con intestazioni
for await (const record of parser) {
try {
// Ogni riga del CSV diventa un oggetto JSON
const item = {
id: record.id || `${Date.now()}-${Math.random().toString(36).substring(2)}`, // Genera un ID univoco se non presente
...record, // Aggiunge tutti i campi del CSV
};
// Inserisci il record nel container
const { resource } = await container.items.create(item);
console.log(`Inserito elemento con ID: ${resource.id}`);
} catch (error) {
console.error("Errore durante l'inserimento:", error);
}
}
console.log("Caricamento completato!");
}
// Esegui la funzione
const csvFilePath = "percorso/del/tuo/file.csv";
uploadCsvToCosmos(csvFilePath).catch((err) => console.error(err));
/*
* Caricamento da csv ottimizzato
*/
import { CosmosClient, BulkOperationType } from "@azure/cosmos";
import * as fs from "fs";
import { parse } from "csv-parse";
// Configurazione di Cosmos DB
const endpoint = "TUO_ENDPOINT_COSMOS_DB";
const key = "TUA_CHIAVE_PRIMARIA";
const databaseId = "TUO_DATABASE";
const containerId = "TUO_CONTAINER";
const client = new CosmosClient({ endpoint, key });
const database = client.database(databaseId);
const container = database.container(containerId);
// Configurazione
const BATCH_SIZE = 100; // Elementi per batch
const CONCURRENT_PROMISES = 10; // Numero di Promise concorrenti
// Funzione per caricare il CSV con bulk ingestion e parallelizzazione
async function uploadCsvToCosmosBulkParallel(csvFilePath: string) {
const parser = fs
.createReadStream(csvFilePath)
.pipe(parse({ columns: true, trim: true }));
let batch = [];
const batches = []; // Array di batch da processare
// Funzione per eseguire il bulk upload con gestione del 409
const executeBulkUpload = async (items: any[]) => {
const operations = items.map(item => ({
operationType: BulkOperationType.Create,
resourceBody: item
}));
try {
const response = await container.items.bulk(operations);
console.log(`Batch di ${items.length} elementi elaborato con successo`);
return response;
} catch (error: any) {
if (error.code === 409) {
// Errore 409: Conflitto, il record esiste già
console.warn(`Conflitto 409 rilevato per alcuni elementi del batch. Dettagli:`, error.message);
return error.response; // Prosegui comunque
} else {
console.error("Errore durante il bulk upload:", error);
throw error; // Lancia l'errore per altri codici
}
}
};
// Raccogli i record in batch
for await (const record of parser) {
const item = {
id: record.id || `${Date.now()}-${Math.random().toString(36).substring(2)}`,
...record,
};
batch.push(item);
if (batch.length >= BATCH_SIZE) {
batches.push([...batch]); // Salva una copia del batch
batch = []; // Resetta il batch corrente
}
}
// Aggiungi eventuali elementi rimanenti
if (batch.length > 0) {
batches.push([...batch]);
}
console.log(`Totale batch da processare: ${batches.length}`);
// Funzione per processare i batch in parallelo con un limite di concorrenza
const processBatchesInParallel = async () => {
const results = [];
for (let i = 0; i < batches.length; i += CONCURRENT_PROMISES) {
const chunk = batches.slice(i, i + CONCURRENT_PROMISES);
const chunkPromises = chunk.map(batch => executeBulkUpload(batch));
try {
const chunkResults = await Promise.all(chunkPromises);
results.push(...chunkResults);
} catch (error) {
console.error("Errore durante l'elaborazione del chunk parallelo:", error);
// Prosegui con il prossimo chunk anche in caso di errore
}
}
return results;
};
// Esegui il processamento parallelo
await processBatchesInParallel();
console.log("Caricamento bulk parallelo completato!");
}
// Esegui la funzione
const csvFilePath = "percorso/del/tuo/file.csv";
uploadCsvToCosmosBulkParallel(csvFilePath).catch((err) => console.error("Errore generale:", err));
<choose>
<when condition="{{cosmosdb-feature-flag}}">
<retry condition="@(((IResponse)context.Variables['cosmosdbResponse']).StatusCode == 429) || ((IResponse)context.Variables['cosmosdbResponse']).StatusCode == 503)" count="3" interval="10" max-interval="40" delta="10" first-fast-retry="false">
<send-request mode="new" response-variable-name="cosmosdbResponse" timeout="15">
<set-url>https://your-cosmosdb-account.documents.azure.com/dbs/your-database-name/colls/your-collection-name/docs/{context.Variables["fiscalCode"]}</set-url>
<set-method>GET</set-method>
<authentication-managed-identity resource="https://cosmos.azure.com" output-token-variable-name="accessToken" />
<!-- <set-header name="Authorization" exists-action="override">
<value>@($"Bearer {context.Variables["accessToken"]}")</value>
</set-header> -->
<set-header name="x-ms-date" exists-action="override">
<value>@(DateTime.UtcNow.ToString("R"))</value>
</set-header>
<set-header name="x-ms-version" exists-action="override">
<value>2018-12-31</value>
</set-header>
<set-header name="Accept" exists-action="override">
<value>application/json</value>
</set-header>
</send-request>
</retry>
<choose>
<when condition="@(((IResponse)context.Variables['cosmosdbResponse']).StatusCode == 200)&& ((IResponse)context.Variables['cosmosdbResponse']).Body != null)">
<otherwise />
</when>
<otherwise>
<return-response>
<set-status code="403" reason="Forbidden" />
<set-body template="liquid">{ "detail": "Access to this resource is forbidden", "status": 403, "title": "Forbidden" }</set-body>
</return-response>
</otherwise>
</choose>
</when>
</choose>
resource "azurerm_role_assignment" "cosmosdb_reader" {
scope = azurerm_cosmosdb_account.cosmos.id
role_definition_name = "Cosmos DB Built-in Data Reader"
principal_id = azurerm_api_management.apim.identity[0].principal_id
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment