corrigindo upload
Deploy / Deploy (push) Failing after 11s
Details
Deploy / Deploy (push) Failing after 11s
Details
This commit is contained in:
parent
b533873e69
commit
a8fdfde48e
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,174 @@
|
||||||
|
bpm: '200'
|
||||||
|
file: floating
|
||||||
|
original_title: floating
|
||||||
|
src: /var/www/html/trens/src_mmpSearch/mmp/floating.mmp
|
||||||
|
tags:
|
||||||
|
TAG:
|
||||||
|
- plugin
|
||||||
|
automation: []
|
||||||
|
bassline: []
|
||||||
|
plugin:
|
||||||
|
- zynaddsubfx
|
||||||
|
sample: []
|
||||||
|
tracks:
|
||||||
|
- arpeggiator:
|
||||||
|
arp: '0'
|
||||||
|
arp-enabled: '0'
|
||||||
|
arpcycle: '0'
|
||||||
|
arpdir: '0'
|
||||||
|
arpgate: '100'
|
||||||
|
arpmiss: '0'
|
||||||
|
arpmode: '0'
|
||||||
|
arprange: '1'
|
||||||
|
arpskip: '0'
|
||||||
|
arptime: '200'
|
||||||
|
arptime_denominator: '4'
|
||||||
|
arptime_numerator: '4'
|
||||||
|
arptime_syncmode: '0'
|
||||||
|
chordcreator:
|
||||||
|
chord: '0'
|
||||||
|
chord-enabled: '0'
|
||||||
|
chordrange: '1'
|
||||||
|
controller:
|
||||||
|
bandwidth_depth: '64'
|
||||||
|
filter_cutoff_depth: '64'
|
||||||
|
filter_q_depth: '64'
|
||||||
|
mod_wheel_depth: '80'
|
||||||
|
panning_depth: '64'
|
||||||
|
pitchwheel_bendrange: '100'
|
||||||
|
portamento_pitchthresh: '3'
|
||||||
|
portamento_pitchthreshtype: '1'
|
||||||
|
portamento_portamento: '0'
|
||||||
|
portamento_propdepth: '90'
|
||||||
|
portamento_proportional: '0'
|
||||||
|
portamento_proprate: '80'
|
||||||
|
portamento_time: '64'
|
||||||
|
portamento_updowntimestretch: '64'
|
||||||
|
resonance_bandwidth_depth: '64'
|
||||||
|
resonance_center_depth: '64'
|
||||||
|
elcut:
|
||||||
|
amt: '0'
|
||||||
|
att: '0'
|
||||||
|
ctlenvamt: '0'
|
||||||
|
dec: '0.5'
|
||||||
|
hold: '0.5'
|
||||||
|
lamt: '0'
|
||||||
|
latt: '0'
|
||||||
|
lpdel: '0'
|
||||||
|
lshp: '0'
|
||||||
|
lspd: '0.1'
|
||||||
|
lspd_denominator: '4'
|
||||||
|
lspd_numerator: '4'
|
||||||
|
lspd_syncmode: '0'
|
||||||
|
pdel: '0'
|
||||||
|
rel: '0.1'
|
||||||
|
sustain: '0.5'
|
||||||
|
userwavefile: ''
|
||||||
|
x100: '0'
|
||||||
|
eldata:
|
||||||
|
fcut: '14000'
|
||||||
|
fres: '0.5'
|
||||||
|
ftype: '0'
|
||||||
|
fwet: '0'
|
||||||
|
elres:
|
||||||
|
amt: '0'
|
||||||
|
att: '0'
|
||||||
|
ctlenvamt: '0'
|
||||||
|
dec: '0.5'
|
||||||
|
hold: '0.5'
|
||||||
|
lamt: '0'
|
||||||
|
latt: '0'
|
||||||
|
lpdel: '0'
|
||||||
|
lshp: '0'
|
||||||
|
lspd: '0.1'
|
||||||
|
lspd_denominator: '4'
|
||||||
|
lspd_numerator: '4'
|
||||||
|
lspd_syncmode: '0'
|
||||||
|
pdel: '0'
|
||||||
|
rel: '0.1'
|
||||||
|
sustain: '0.5'
|
||||||
|
userwavefile: ''
|
||||||
|
x100: '0'
|
||||||
|
elvol:
|
||||||
|
amt: '0'
|
||||||
|
att: '0'
|
||||||
|
ctlenvamt: '0'
|
||||||
|
dec: '0.5'
|
||||||
|
hold: '0.5'
|
||||||
|
lamt: '0'
|
||||||
|
latt: '0'
|
||||||
|
lpdel: '0'
|
||||||
|
lshp: '0'
|
||||||
|
lspd: '0.1'
|
||||||
|
lspd_denominator: '4'
|
||||||
|
lspd_numerator: '4'
|
||||||
|
lspd_syncmode: '0'
|
||||||
|
pdel: '0'
|
||||||
|
rel: '0.1'
|
||||||
|
sustain: '0.5'
|
||||||
|
userwavefile: ''
|
||||||
|
x100: '0'
|
||||||
|
fxchain:
|
||||||
|
enabled: '0'
|
||||||
|
numofeffects: '0'
|
||||||
|
insertion_effects:
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
- part: '-1'
|
||||||
|
type: '0'
|
||||||
|
instrument_effects:
|
||||||
|
- par: '119'
|
||||||
|
preset: '0'
|
||||||
|
route: '0'
|
||||||
|
type: '3'
|
||||||
|
- route: '0'
|
||||||
|
type: '0'
|
||||||
|
- route: '0'
|
||||||
|
type: '0'
|
||||||
|
instrument_name: zynaddsubfx
|
||||||
|
instrumenttrack:
|
||||||
|
basenote: '57'
|
||||||
|
fxch: '0'
|
||||||
|
pan: '0'
|
||||||
|
pitch: '0'
|
||||||
|
pitchrange: '1'
|
||||||
|
usemasterpitch: '1'
|
||||||
|
vol: '100'
|
||||||
|
midiport:
|
||||||
|
basevelocity: '63'
|
||||||
|
fixedinputvelocity: '-1'
|
||||||
|
fixedoutputnote: '-1'
|
||||||
|
fixedoutputvelocity: '-1'
|
||||||
|
inputchannel: '0'
|
||||||
|
inputcontroller: '0'
|
||||||
|
outputchannel: '1'
|
||||||
|
outputcontroller: '0'
|
||||||
|
outputprogram: '1'
|
||||||
|
readable: '0'
|
||||||
|
writable: '0'
|
||||||
|
system_effects:
|
||||||
|
- send_vol: '0'
|
||||||
|
type: '0'
|
||||||
|
vol: '0'
|
||||||
|
- send_vol: '0'
|
||||||
|
type: '0'
|
||||||
|
vol: '0'
|
||||||
|
- send_vol: '0'
|
||||||
|
type: '0'
|
||||||
|
vol: '0'
|
||||||
|
- type: '0'
|
||||||
|
vol: '0'
|
||||||
|
track_name: Ice Rhodes3
|
||||||
|
type: plugin
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,6 +6,9 @@
|
||||||
"bassdrum_acoustic02_-_Copia.ogg": {
|
"bassdrum_acoustic02_-_Copia.ogg": {
|
||||||
"_isFile": true
|
"_isFile": true
|
||||||
},
|
},
|
||||||
|
"bassdrum01.ogg": {
|
||||||
|
"_isFile": true
|
||||||
|
},
|
||||||
"bassdrum_acoustic01_-_Copia.ogg": {
|
"bassdrum_acoustic01_-_Copia.ogg": {
|
||||||
"_isFile": true
|
"_isFile": true
|
||||||
},
|
},
|
||||||
|
|
@ -15,6 +18,9 @@
|
||||||
"bassdrum03_-_Copia.ogg": {
|
"bassdrum03_-_Copia.ogg": {
|
||||||
"_isFile": true
|
"_isFile": true
|
||||||
},
|
},
|
||||||
|
"bassdrum_acoustic01.ogg": {
|
||||||
|
"_isFile": true
|
||||||
|
},
|
||||||
"bassdrum02_-_Copia.ogg": {
|
"bassdrum02_-_Copia.ogg": {
|
||||||
"_isFile": true
|
"_isFile": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
_data/users.db
BIN
_data/users.db
Binary file not shown.
|
|
@ -1,5 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import concurrent.futures # NOVO: Necessário para usar o ProcessPoolExecutor
|
import concurrent.futures # NOVO: Necessário para usar o ProcessPoolExecutor
|
||||||
import csv
|
import csv
|
||||||
|
|
@ -7,6 +6,7 @@ import time
|
||||||
import glob
|
import glob
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
|
||||||
# ================= 1. LIMITADOR DE CPU DINÂMICO =================
|
# ================= 1. LIMITADOR DE CPU DINÂMICO =================
|
||||||
def configurar_limites_cpu():
|
def configurar_limites_cpu():
|
||||||
try:
|
try:
|
||||||
|
|
@ -28,6 +28,7 @@ def configurar_limites_cpu():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Aviso: Não foi possível limitar CPU automaticamente: {e}")
|
print(f"Aviso: Não foi possível limitar CPU automaticamente: {e}")
|
||||||
|
|
||||||
|
|
||||||
configurar_limites_cpu()
|
configurar_limites_cpu()
|
||||||
|
|
||||||
# ================= IMPORTS =================
|
# ================= IMPORTS =================
|
||||||
|
|
@ -84,6 +85,7 @@ GLOBAL_EMBEDDING = None
|
||||||
GLOBAL_CLASSIFIER = None
|
GLOBAL_CLASSIFIER = None
|
||||||
GLOBAL_CLASSES = None
|
GLOBAL_CLASSES = None
|
||||||
|
|
||||||
|
|
||||||
# ================= CLASSE DE AUDITORIA OTIMIZADA =================
|
# ================= CLASSE DE AUDITORIA OTIMIZADA =================
|
||||||
class Auditoria:
|
class Auditoria:
|
||||||
def __init__(self, arquivo_csv):
|
def __init__(self, arquivo_csv):
|
||||||
|
|
@ -110,7 +112,9 @@ class Auditoria:
|
||||||
)
|
)
|
||||||
self.file.flush()
|
self.file.flush()
|
||||||
|
|
||||||
def registrar_processamento(self, nome_arquivo, tamanho_bytes, duracao_audio, tempo_gasto):
|
def registrar_processamento(
|
||||||
|
self, nome_arquivo, tamanho_bytes, duracao_audio, tempo_gasto
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
ram_mb = self.process.memory_info().rss / (1024 * 1024)
|
ram_mb = self.process.memory_info().rss / (1024 * 1024)
|
||||||
cpu_pct = self.process.cpu_percent(interval=None)
|
cpu_pct = self.process.cpu_percent(interval=None)
|
||||||
|
|
@ -134,7 +138,7 @@ class Auditoria:
|
||||||
logging.error(f"Erro ao auditar arquivo: {e}")
|
logging.error(f"Erro ao auditar arquivo: {e}")
|
||||||
|
|
||||||
def verificar_marco(self, contagem):
|
def verificar_marco(self, contagem):
|
||||||
pass # Você pode customizar logs de progresso aqui depois se quiser
|
pass # Você pode customizar logs de progresso aqui depois se quiser
|
||||||
|
|
||||||
def fechar(self):
|
def fechar(self):
|
||||||
try:
|
try:
|
||||||
|
|
@ -145,6 +149,7 @@ class Auditoria:
|
||||||
|
|
||||||
# ================= FUNÇÕES AUXILIARES =================
|
# ================= FUNÇÕES AUXILIARES =================
|
||||||
|
|
||||||
|
|
||||||
def verificar_memoria_segura(tamanho_arquivo_bytes):
|
def verificar_memoria_segura(tamanho_arquivo_bytes):
|
||||||
mem = psutil.virtual_memory()
|
mem = psutil.virtual_memory()
|
||||||
livre_mb = mem.available / (1024 * 1024)
|
livre_mb = mem.available / (1024 * 1024)
|
||||||
|
|
@ -225,7 +230,9 @@ def carregar_database_yaml():
|
||||||
logging.error(f"Erro ao ler lote {arquivo}: {e}")
|
logging.error(f"Erro ao ler lote {arquivo}: {e}")
|
||||||
print(f"X Erro ao ler {os.path.basename(arquivo)}")
|
print(f"X Erro ao ler {os.path.basename(arquivo)}")
|
||||||
|
|
||||||
print(f"--- Total de Projetos no DB (Memória): {len(db)} (de {total_carregados} lidos) ---")
|
print(
|
||||||
|
f"--- Total de Projetos no DB (Memória): {len(db)} (de {total_carregados} lidos) ---"
|
||||||
|
)
|
||||||
return db
|
return db
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -300,14 +307,14 @@ def calcular_complexidade(projeto_yaml):
|
||||||
score += num_fx * W_FX
|
score += num_fx * W_FX
|
||||||
stats["num_effects"] += num_fx
|
stats["num_effects"] += num_fx
|
||||||
|
|
||||||
if score <= 15:
|
if score <= 120:
|
||||||
estrelas = 1
|
estrelas = 4
|
||||||
elif score <= 40:
|
|
||||||
estrelas = 2
|
|
||||||
elif score <= 80:
|
elif score <= 80:
|
||||||
estrelas = 3
|
estrelas = 3
|
||||||
elif score <= 120:
|
elif score <= 40:
|
||||||
estrelas = 4
|
estrelas = 2
|
||||||
|
elif score <= 15:
|
||||||
|
estrelas = 1
|
||||||
else:
|
else:
|
||||||
estrelas = 5
|
estrelas = 5
|
||||||
|
|
||||||
|
|
@ -316,6 +323,7 @@ def calcular_complexidade(projeto_yaml):
|
||||||
|
|
||||||
# ================= NÚCLEO DE ANÁLISE =================
|
# ================= NÚCLEO DE ANÁLISE =================
|
||||||
|
|
||||||
|
|
||||||
def detectar_estrutura(audio_vec, sample_rate, duration):
|
def detectar_estrutura(audio_vec, sample_rate, duration):
|
||||||
try:
|
try:
|
||||||
if duration < 30:
|
if duration < 30:
|
||||||
|
|
@ -496,7 +504,9 @@ def analisar_faixa(caminho_arquivo, embedding_model, classifier_model, classes_r
|
||||||
|
|
||||||
metadata["analise_ia"] = {
|
metadata["analise_ia"] = {
|
||||||
"genero_macro": genero_pai,
|
"genero_macro": genero_pai,
|
||||||
"estilo_principal": tags_detectadas[0]["tag"] if tags_detectadas else "Unknown",
|
"estilo_principal": tags_detectadas[0]["tag"]
|
||||||
|
if tags_detectadas
|
||||||
|
else "Unknown",
|
||||||
"nuvem_tags": tags_detectadas,
|
"nuvem_tags": tags_detectadas,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,6 +535,7 @@ def worker_analise(caminho):
|
||||||
global GLOBAL_EMBEDDING, GLOBAL_CLASSIFIER, GLOBAL_CLASSES
|
global GLOBAL_EMBEDDING, GLOBAL_CLASSIFIER, GLOBAL_CLASSES
|
||||||
return analisar_faixa(caminho, GLOBAL_EMBEDDING, GLOBAL_CLASSIFIER, GLOBAL_CLASSES)
|
return analisar_faixa(caminho, GLOBAL_EMBEDDING, GLOBAL_CLASSIFIER, GLOBAL_CLASSES)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print("\n--- INICIANDO PROCESSADOR + AUDITORIA ---")
|
print("\n--- INICIANDO PROCESSADOR + AUDITORIA ---")
|
||||||
|
|
||||||
|
|
@ -549,11 +560,27 @@ def main():
|
||||||
print(f"Auditoria será salva em: {ARQUIVO_AUDITORIA}")
|
print(f"Auditoria será salva em: {ARQUIVO_AUDITORIA}")
|
||||||
|
|
||||||
# === CARREGAMENTO MODELOS GLOBAIS ===
|
# === CARREGAMENTO MODELOS GLOBAIS ===
|
||||||
path_embed = MODELO_EMBEDDING if os.path.exists(MODELO_EMBEDDING) else os.path.join(BASE_DIR, MODELO_EMBEDDING)
|
path_embed = (
|
||||||
path_class = MODELO_CLASSIFIER if os.path.exists(MODELO_CLASSIFIER) else os.path.join(BASE_DIR, MODELO_CLASSIFIER)
|
MODELO_EMBEDDING
|
||||||
path_json = MODELO_CLASSES if os.path.exists(MODELO_CLASSES) else os.path.join(BASE_DIR, MODELO_CLASSES)
|
if os.path.exists(MODELO_EMBEDDING)
|
||||||
|
else os.path.join(BASE_DIR, MODELO_EMBEDDING)
|
||||||
|
)
|
||||||
|
path_class = (
|
||||||
|
MODELO_CLASSIFIER
|
||||||
|
if os.path.exists(MODELO_CLASSIFIER)
|
||||||
|
else os.path.join(BASE_DIR, MODELO_CLASSIFIER)
|
||||||
|
)
|
||||||
|
path_json = (
|
||||||
|
MODELO_CLASSES
|
||||||
|
if os.path.exists(MODELO_CLASSES)
|
||||||
|
else os.path.join(BASE_DIR, MODELO_CLASSES)
|
||||||
|
)
|
||||||
|
|
||||||
if os.path.exists(path_embed) and os.path.exists(path_class) and os.path.exists(path_json):
|
if (
|
||||||
|
os.path.exists(path_embed)
|
||||||
|
and os.path.exists(path_class)
|
||||||
|
and os.path.exists(path_json)
|
||||||
|
):
|
||||||
print("--- Carregando Modelos de IA ---")
|
print("--- Carregando Modelos de IA ---")
|
||||||
try:
|
try:
|
||||||
with open(path_json, "r") as f:
|
with open(path_json, "r") as f:
|
||||||
|
|
@ -561,13 +588,23 @@ def main():
|
||||||
|
|
||||||
print("[1/2] Carregando Extrator de Embeddings...")
|
print("[1/2] Carregando Extrator de Embeddings...")
|
||||||
if hasattr(es, "TensorflowPredictEffnetDiscogs"):
|
if hasattr(es, "TensorflowPredictEffnetDiscogs"):
|
||||||
GLOBAL_EMBEDDING = es.TensorflowPredictEffnetDiscogs(graphFilename=path_embed, output="PartitionedCall:1")
|
GLOBAL_EMBEDDING = es.TensorflowPredictEffnetDiscogs(
|
||||||
|
graphFilename=path_embed, output="PartitionedCall:1"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
print(" -> Usando TensorflowPredict genérico.")
|
print(" -> Usando TensorflowPredict genérico.")
|
||||||
GLOBAL_EMBEDDING = es.TensorflowPredict(graphFilename=path_embed, input="serving_default_model_Placeholder", output="PartitionedCall:1")
|
GLOBAL_EMBEDDING = es.TensorflowPredict(
|
||||||
|
graphFilename=path_embed,
|
||||||
|
input="serving_default_model_Placeholder",
|
||||||
|
output="PartitionedCall:1",
|
||||||
|
)
|
||||||
print(" -> Embeddings carregados com sucesso.")
|
print(" -> Embeddings carregados com sucesso.")
|
||||||
|
|
||||||
GLOBAL_CLASSIFIER = es.TensorflowPredict2D(graphFilename=path_class, input="serving_default_model_Placeholder", output="PartitionedCall:0")
|
GLOBAL_CLASSIFIER = es.TensorflowPredict2D(
|
||||||
|
graphFilename=path_class,
|
||||||
|
input="serving_default_model_Placeholder",
|
||||||
|
output="PartitionedCall:0",
|
||||||
|
)
|
||||||
print("[2/2] Classificador de Gênero carregado.")
|
print("[2/2] Classificador de Gênero carregado.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -587,11 +624,19 @@ def main():
|
||||||
contagem_sessao = 0
|
contagem_sessao = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with concurrent.futures.ProcessPoolExecutor(max_workers=max_workers) as executor:
|
with concurrent.futures.ProcessPoolExecutor(
|
||||||
resultados_futuros = {executor.submit(worker_analise, caminho): caminho for caminho in a_fazer}
|
max_workers=max_workers
|
||||||
|
) as executor:
|
||||||
|
resultados_futuros = {
|
||||||
|
executor.submit(worker_analise, caminho): caminho for caminho in a_fazer
|
||||||
|
}
|
||||||
|
|
||||||
# O as_completed processa os que terminam mais rápido em vez de travar na ordem
|
# O as_completed processa os que terminam mais rápido em vez de travar na ordem
|
||||||
for future in tqdm(concurrent.futures.as_completed(resultados_futuros), total=len(a_fazer), unit="track"):
|
for future in tqdm(
|
||||||
|
concurrent.futures.as_completed(resultados_futuros),
|
||||||
|
total=len(a_fazer),
|
||||||
|
unit="track",
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
res, duracao, tempo_gasto = future.result()
|
res, duracao, tempo_gasto = future.result()
|
||||||
caminho = resultados_futuros[future]
|
caminho = resultados_futuros[future]
|
||||||
|
|
@ -601,7 +646,9 @@ def main():
|
||||||
lista_resultados.append(res)
|
lista_resultados.append(res)
|
||||||
|
|
||||||
tamanho = os.path.getsize(caminho)
|
tamanho = os.path.getsize(caminho)
|
||||||
auditor.registrar_processamento(res['arquivo'], tamanho, duracao, tempo_gasto)
|
auditor.registrar_processamento(
|
||||||
|
res["arquivo"], tamanho, duracao, tempo_gasto
|
||||||
|
)
|
||||||
|
|
||||||
contagem_sessao += 1
|
contagem_sessao += 1
|
||||||
auditor.verificar_marco(contagem_sessao)
|
auditor.verificar_marco(contagem_sessao)
|
||||||
|
|
@ -613,7 +660,7 @@ def main():
|
||||||
print("\nParando paralelismo graciosamente...")
|
print("\nParando paralelismo graciosamente...")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
auditor.fechar() # Fecha o CSV com segurança
|
auditor.fechar() # Fecha o CSV com segurança
|
||||||
|
|
||||||
tempo_total_sessao = time.time() - auditor.inicio_global
|
tempo_total_sessao = time.time() - auditor.inicio_global
|
||||||
print("\n--- FIM DO PROCESSAMENTO ---")
|
print("\n--- FIM DO PROCESSAMENTO ---")
|
||||||
|
|
|
||||||
|
|
@ -133,12 +133,12 @@ def calcular_nivel_ponderado(
|
||||||
pontos += 1
|
pontos += 1
|
||||||
|
|
||||||
# 3. Estrutura (Áudio)
|
# 3. Estrutura (Áudio)
|
||||||
if qtd_secoes_audio >= 3:
|
if qtd_secoes_audio >= 10:
|
||||||
pontos += 1.5
|
pontos += 5
|
||||||
elif qtd_secoes_audio >= 5:
|
elif qtd_secoes_audio >= 5:
|
||||||
pontos += 3
|
pontos += 3
|
||||||
elif qtd_secoes_audio >= 10:
|
elif qtd_secoes_audio >= 3:
|
||||||
pontos += 5
|
pontos += 1.5
|
||||||
|
|
||||||
if pontos < 3:
|
if pontos < 3:
|
||||||
return "Iniciante"
|
return "Iniciante"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import shutil
|
||||||
import time
|
import time
|
||||||
import io
|
import io
|
||||||
import threading
|
import threading
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
from flask import Flask, request, jsonify, send_file, redirect
|
from flask import Flask, request, jsonify, send_file, redirect
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
|
@ -41,6 +42,15 @@ from utils import (
|
||||||
SAMPLE_MANIFEST,
|
SAMPLE_MANIFEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO
|
||||||
|
) # obriga o servidor a mostrar os sucessos também
|
||||||
|
|
||||||
|
# Trava do build do Jekyll
|
||||||
|
JEKYLL_LOCK = Lock()
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# --- CONFIGURAÇÃO DE SEGURANÇA E BANCO ---
|
# --- CONFIGURAÇÃO DE SEGURANÇA E BANCO ---
|
||||||
|
|
@ -164,17 +174,13 @@ def allowed_sample(filename):
|
||||||
and filename.rsplit(".", 1)[1].lower() in ALLOWED_SAMPLE_EXTENSIONS
|
and filename.rsplit(".", 1)[1].lower() in ALLOWED_SAMPLE_EXTENSIONS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_jekyll_build():
|
def run_jekyll_build():
|
||||||
RUBY_BIN_PATH = "/usr/bin/ruby3.2"
|
RUBY_BIN_PATH = "/usr/bin/ruby3.2"
|
||||||
BUNDLE_PATH = (
|
BUNDLE_PATH = "/nethome/jotachina/projetos/mmpSearch/vendor/bundle/ruby/3.2.0/bin/bundle"
|
||||||
"/nethome/jotachina/projetos/mmpSearch/vendor/bundle/ruby/3.2.0/bin/bundle"
|
|
||||||
)
|
|
||||||
# Prepara o ambiente para o subprocesso
|
|
||||||
env_vars = os.environ.copy()
|
env_vars = os.environ.copy()
|
||||||
# Adiciona o caminho do Ruby ao PATH do usuário www-data temporariamente
|
|
||||||
env_vars["PATH"] = f"{RUBY_BIN_PATH}:{env_vars.get('PATH', '')}"
|
env_vars["PATH"] = f"{RUBY_BIN_PATH}:{env_vars.get('PATH', '')}"
|
||||||
print("Iniciando build do Jekyll...")
|
|
||||||
command = [
|
command = [
|
||||||
BUNDLE_PATH,
|
BUNDLE_PATH,
|
||||||
"exec",
|
"exec",
|
||||||
|
|
@ -183,18 +189,24 @@ def run_jekyll_build():
|
||||||
"--destination",
|
"--destination",
|
||||||
"/var/www/html/trens/mmpSearch/",
|
"/var/www/html/trens/mmpSearch/",
|
||||||
]
|
]
|
||||||
try:
|
|
||||||
# Redirecionamos a saída para DEVNULL para não encher o buffer e travar
|
logging.info("⏳ Aguardando liberação para iniciar build do Jekyll...")
|
||||||
subprocess.Popen(
|
with JEKYLL_LOCK:
|
||||||
command,
|
logging.info("🔨 Iniciando build do Jekyll (Travando a fila)...")
|
||||||
cwd=BASE_DATA,
|
try:
|
||||||
env=env_vars,
|
resultado = subprocess.run(
|
||||||
stdout=subprocess.DEVNULL,
|
command,
|
||||||
stderr=subprocess.DEVNULL,
|
cwd=BASE_DATA,
|
||||||
)
|
env=env_vars,
|
||||||
print("Jekyll Build iniciado em segundo plano (background).")
|
capture_output=True,
|
||||||
except Exception as e:
|
text=True,
|
||||||
print(f"Erro ao iniciar Jekyll: {e}")
|
check=True
|
||||||
|
)
|
||||||
|
logging.info("✅ Jekyll Build concluído com sucesso!")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
logging.error(f"❌ ERRO FATAL no Jekyll Build (Code {e.returncode}):\n{e.stderr}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"❌ Erro inesperado ao chamar Jekyll: {e}")
|
||||||
|
|
||||||
|
|
||||||
def load_manifest_keys():
|
def load_manifest_keys():
|
||||||
|
|
@ -321,31 +333,27 @@ def update_xml_paths_exact(mmp_filename, replacements):
|
||||||
|
|
||||||
|
|
||||||
def run_heavy_tasks_in_background():
|
def run_heavy_tasks_in_background():
|
||||||
"""Esta função roda isolada sem travar o usuário"""
|
logging.info("--- [BACKGROUND] Iniciando tarefas assíncronas ---")
|
||||||
print("--- [BACKGROUND] Iniciando reconstrução de índices ---")
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# 2. Isso gera os manifestos (Python puro)
|
|
||||||
generate_manifests(SRC_MMPSEARCH)
|
generate_manifests(SRC_MMPSEARCH)
|
||||||
|
|
||||||
# 3. Isso chama o subprocesso do Jekyll (Externo)
|
|
||||||
# Mantém sua função original que usa subprocess
|
|
||||||
run_jekyll_build()
|
run_jekyll_build()
|
||||||
|
logging.info("--- [BACKGROUND] Todas as tarefas concluídas ---")
|
||||||
print("--- [BACKGROUND] Tarefas concluídas com sucesso ---")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"--- [BACKGROUND] Erro: {e} ---")
|
logging.error(f"--- [BACKGROUND] Erro: {e} ---")
|
||||||
|
|
||||||
|
|
||||||
def process_and_build(filename):
|
def process_and_build(filename):
|
||||||
"""Função chamada pela rota de upload"""
|
"""Função chamada pela rota de upload"""
|
||||||
# Processamento inicial do arquivo (rápido)
|
|
||||||
result = process_single_file(filename)
|
# 1. Preparamos os 3 dados que o main.py exige: (file_name, clean_slug, total_files)
|
||||||
|
name_without_ext = os.path.splitext(filename)[0]
|
||||||
|
clean_slug = slugify(name_without_ext)
|
||||||
|
args_tuple = (filename, clean_slug, 1) # O 1 representa que é só 1 arquivo no total
|
||||||
|
|
||||||
|
# 2. Passamos a tupla!
|
||||||
|
result = process_single_file(args_tuple)
|
||||||
|
|
||||||
if result["success"]:
|
if result["success"]:
|
||||||
# Em vez de chamar rebuild_indexes() direto, criamos a Thread
|
# Em vez de chamar rebuild_indexes() direto, criamos a Thread
|
||||||
# O Flask vai responder o return abaixo imediatamente,
|
|
||||||
# enquanto a thread continua rodando no servidor.
|
|
||||||
task_thread = threading.Thread(target=run_heavy_tasks_in_background)
|
task_thread = threading.Thread(target=run_heavy_tasks_in_background)
|
||||||
task_thread.start()
|
task_thread.start()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue