Help

30s limit how to deceive

34 1
cancel
Showing results for 
Search instead for 
Did you mean: 
cimirio
4 - Data Explorer
4 - Data Explorer

I'm working on a project where I have 3 tables in play.
"Database" - "Data2" - "Match"

The script I developed allows me to take a record from the "Data2" table, compare it with each record from the "Database" table and if there is a correspondence between the two, based on 3 specific values ​​which are multiple choice fields, then it is created a new record in the "Match" table
The automation starts n times based on the number of records flagged in the "Data2" table

The problem is that having more than 1000 records in the "Database" table, even if I have optimized the script as much as possible, in some cases I run into the 30s limit

I show you the current code:

// Ottieni le variabili di input
let inputConfig = input.config();
let nomeBando = inputConfig.nomeBando;
let areaInteresse = inputConfig.areaInteresse || [];
let tipologiaSoggetto = inputConfig.tipologiaSoggetto || [];
let settore = inputConfig.settore || [];
let bandoContributiRecordId = inputConfig.recordId;
let scadenza = inputConfig.scadenza;
let dataScadenza = inputConfig.dataScadenza;
let scadenzaBando = inputConfig.scadenzaBando;

// Assicurati che le variabili multi-selezione siano array
if (!Array.isArray(areaInteresse)) areaInteresse = [areaInteresse];
if (!Array.isArray(tipologiaSoggetto)) tipologiaSoggetto = [tipologiaSoggetto];
if (!Array.isArray(settore)) settore = [settore];

// Definizione delle tabelle
let dbTable = base.getTable("Aziende DB");
let matchTable = base.getTable("Match [AziendeDB | Bandi]");

// Funzione per controllare se c'è una corrispondenza tra due array
function hasMatch(array1, array2) {
    if (!Array.isArray(array2)) array2 = [array2];
    return array1.some(item => array2.includes(item));
}

// Funzione per normalizzare i valori prima di inserire i dati
function sanitizeValue(value, fieldName) {
    if (value === undefined || value === null) {
        return null;
    }
    if (["Area di interesse", "Tipologia Soggetto Giuridico", "Settore"].includes(fieldName)) {
        return Array.isArray(value) ? value : [];
    }
    return value ? String(value) : null;
}

// Ottieni i record esistenti nella tabella Match
let existingMatches = await matchTable.selectRecordsAsync({
    fields: ["Nome bando", "ID record Azienda"]
});

// Funzione per verificare se il match esiste già
function isDuplicateMatch(nomeBando, idAzienda) {
    return existingMatches.records.some(match =>
        match.getCellValue("Nome bando") === nomeBando &&
        match.getCellValue("ID record Azienda") === idAzienda
    );
}

// Esegui la query senza filtro
let query = await dbTable.selectRecordsAsync({
    fields: [
        "Area di interesse", 
        "Tipologia Soggetto Giuridico", 
        "Settore", 
        "Ragione Sociale", 
        "Indirizzo", 
        "Email", 
        "ID Tipologia (from Collegamento Tipologia)",
        "ID Record"
    ]
});

// Processa i record in parallelo
async function processInParallel(records) {
    const batchSize = 50;
    for (let i = 0; i < records.length; i += batchSize) {
        const batch = records.slice(i, i + batchSize);

        await Promise.all(batch.map(async (record) => {
            await processSingleRecord(record);
        }));
    }
}

async function processSingleRecord(record) {
    let isMatch = false;

    if (areaInteresse.includes("Nazionale")) {
        let dbTipologiaSoggetto = (record.getCellValue("Tipologia Soggetto Giuridico") || []).map(item => item.name);
        let dbSettore = (record.getCellValue("Settore") || []).map(item => item.name);
        isMatch = hasMatch(tipologiaSoggetto, dbTipologiaSoggetto) && hasMatch(settore, dbSettore);
    } else {
        let dbAreaInteresse = (record.getCellValue("Area di interesse") || []).map(item => item.name);
        let dbTipologiaSoggetto = (record.getCellValue("Tipologia Soggetto Giuridico") || []).map(item => item.name);
        let dbSettore = (record.getCellValue("Settore") || []).map(item => item.name);
        isMatch = hasMatch(areaInteresse, dbAreaInteresse) && hasMatch(tipologiaSoggetto, dbTipologiaSoggetto) && hasMatch(settore, dbSettore);
    }

    if (isMatch) {
        let newRecord = {
            "Nome bando": sanitizeValue(nomeBando, "Nome bando"),
            "Scadenza": sanitizeValue(scadenza, "Scadenza"),
            "Data Scadenza": sanitizeValue(dataScadenza, "Data Scadenza"),
            "Scadenza Bando": sanitizeValue(scadenzaBando, "Scadenza Bando"),
            "Ragione Sociale": sanitizeValue(record.getCellValue("Ragione Sociale"), "Ragione Sociale"),
            "Indirizzo": sanitizeValue(record.getCellValue("Indirizzo"), "Indirizzo"),
            "Email": sanitizeValue(record.getCellValue("Email"), "Email"),
            "ID Tipologia (from Collegamento Tipologia)": sanitizeValue(record.getCellValue("ID Tipologia (from Collegamento Tipologia)"), "ID Tipologia (from Collegamento Tipologia)"),
            "ID record Azienda": sanitizeValue(record.getCellValue("ID Record"), "ID record")
        };

        if (!areaInteresse.includes("Nazionale")) {
            newRecord["Area di interesse"] = record.getCellValue("Area di interesse");
        }
        newRecord["Tipologia Soggetto Giuridico"] = record.getCellValue("Tipologia Soggetto Giuridico");
        newRecord["Settore"] = record.getCellValue("Settore");

        // Crea il match solo se non è duplicato
        if (!isDuplicateMatch(nomeBando, record.getCellValue("ID Record"))) {
            await matchTable.createRecordAsync(newRecord);
        } else {
            console.log(`Match già esistente: Nome bando: ${nomeBando}, ID Azienda: ${record.getCellValue("ID Record")}`);
        }
    }
}

await processInParallel(query.records);
console.log("Script completato con successo.");

The idea that came to me is to take the current code outside (e.g. Google Cloud) so as to avoid the 30s, the problem is that by taking it outside and setting everything correctly the match is not carried out due to some inconsistencies when reading the data.
I hypothesized it is a problem reading the data in the multiple choice fields which are the ones that verify whether the match exists or not.

Do you have correct solutions and/or implementations to bring out the script in the right way?

Thank you!!

1 Reply 1

Hello @cimirio,
Airtable Automation Run Script step has a couple of restrictions. 

You should be aware of Airtable automation run script limitations as per time and resources. https://support.airtable.com/docs/run-a-script-action#run-a-script-action-limits

👍