{
  "name": "События в PostgreSQL без дублей: ON CONFLICT и транзакция",
  "nodes": [
    {
      "parameters": {
        "content": "## События в Postgres\nПачка до 50 событий пишется одной транзакцией: упала одна вставка — откатывается вся пачка, состояния «половина записана» нет. Повтор того же event_id гасит ON CONFLICT DO NOTHING по уникальному индексу.\n\nПосле импорта: подключение к базе (пользователю нужны только INSERT и SELECT на events).",
        "width": 560,
        "height": 220
      },
      "id": "f410456d-31a4-52cc-b6c9-036133eabfd7",
      "name": "Заметка 7aa920",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -40,
        -280
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "events",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "14a8480d-3d2d-53af-b0c9-bb1c779e03ea",
      "name": "События",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "webhookId": "fdf1bec1-d7a0-58f4-83dd-831ee8182a7d"
    },
    {
      "parameters": {
        "fieldToSplitOut": "body.events",
        "options": {}
      },
      "id": "0f508037-065c-5362-820d-fd1efb555b7b",
      "name": "По одному событию",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO events (event_id, type, payload, created_at)\nVALUES ($1, $2, $3::jsonb, $4)\nON CONFLICT (event_id) DO NOTHING\nRETURNING event_id;",
        "options": {
          "queryReplacement": "={{ [$json.event_id, $json.type, JSON.stringify($json.payload), $json.created_at] }}",
          "queryBatching": "transaction"
        }
      },
      "id": "0d2c63b5-eff3-52c3-a614-7800e0f3a292",
      "name": "Записать",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        440,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 3000
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"written\": $input.all().length } }}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "a5907bdb-aa85-5e73-9490-a558c77a3730",
      "name": "Ответ",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        660,
        0
      ]
    }
  ],
  "connections": {
    "События": {
      "main": [
        [
          {
            "node": "По одному событию",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "По одному событию": {
      "main": [
        [
          {
            "node": "Записать",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Записать": {
      "main": [
        [
          {
            "node": "Ответ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "active": false,
  "meta": {
    "templateCredsSetupCompleted": false,
    "source": "promtbaza.com/voprosy/shablony-n8n"
  }
}