|
6 | 6 | "errors" |
7 | 7 | "fmt" |
8 | 8 | "log" |
| 9 | + "math/rand" |
9 | 10 | "sort" |
10 | 11 | "sync" |
11 | 12 | "time" |
@@ -1459,9 +1460,17 @@ func (r *OLAPRepositoryImpl) writeTaskEventBatch(ctx context.Context, tenantId s |
1459 | 1460 | } |
1460 | 1461 |
|
1461 | 1462 | if event.ExternalID.Valid { |
| 1463 | + // generating a dummy id + inserted at to use for creating the external keys for the task events |
| 1464 | + // we do this since we don't have the id + inserted at of the events themselves on the opts, and we don't |
| 1465 | + // actually need those for anything once the keys are created. |
| 1466 | + dummyId := rand.Int63() |
| 1467 | + // randomly jitter the inserted at time by +/- 300ms to make collisions virtually impossible |
| 1468 | + dummyInsertedAt := time.Now().Add(time.Duration(rand.Intn(2*300+1)-300) * time.Millisecond) |
| 1469 | + |
1462 | 1470 | payloadsToWrite = append(payloadsToWrite, StoreOLAPPayloadOpts{ |
| 1471 | + Id: dummyId, |
1463 | 1472 | ExternalId: event.ExternalID, |
1464 | | - InsertedAt: event.TaskInsertedAt, |
| 1473 | + InsertedAt: sqlchelpers.TimestamptzFromTime(dummyInsertedAt), |
1465 | 1474 | Payload: event.Output, |
1466 | 1475 | }) |
1467 | 1476 | } |
@@ -1772,6 +1781,7 @@ func (r *OLAPRepositoryImpl) writeTaskBatch(ctx context.Context, tenantId string |
1772 | 1781 | }) |
1773 | 1782 |
|
1774 | 1783 | putPayloadOpts = append(putPayloadOpts, StoreOLAPPayloadOpts{ |
| 1784 | + Id: task.ID, |
1775 | 1785 | ExternalId: task.ExternalID, |
1776 | 1786 | InsertedAt: task.InsertedAt, |
1777 | 1787 | Payload: payload, |
@@ -1833,6 +1843,7 @@ func (r *OLAPRepositoryImpl) writeDAGBatch(ctx context.Context, tenantId string, |
1833 | 1843 | }) |
1834 | 1844 |
|
1835 | 1845 | putPayloadOpts = append(putPayloadOpts, StoreOLAPPayloadOpts{ |
| 1846 | + Id: dag.ID, |
1836 | 1847 | ExternalId: dag.ExternalID, |
1837 | 1848 | InsertedAt: dag.InsertedAt, |
1838 | 1849 | Payload: dag.Input, |
@@ -2049,29 +2060,6 @@ func (r *OLAPRepositoryImpl) BulkCreateEventsAndTriggers(ctx context.Context, ev |
2049 | 2060 | return fmt.Errorf("error creating events: %v", err) |
2050 | 2061 | } |
2051 | 2062 |
|
2052 | | - tenantIdToPutPayloadOpts := make(map[string][]StoreOLAPPayloadOpts) |
2053 | | - |
2054 | | - for _, event := range insertedEvents { |
2055 | | - if event == nil { |
2056 | | - continue |
2057 | | - } |
2058 | | - |
2059 | | - tenantIdToPutPayloadOpts[event.TenantID.String()] = append(tenantIdToPutPayloadOpts[event.TenantID.String()], StoreOLAPPayloadOpts{ |
2060 | | - ExternalId: event.ExternalID, |
2061 | | - InsertedAt: event.SeenAt, |
2062 | | - Payload: event.Payload, |
2063 | | - }) |
2064 | | - |
2065 | | - } |
2066 | | - |
2067 | | - for tenantId, putPayloadOpts := range tenantIdToPutPayloadOpts { |
2068 | | - err = r.PutPayloads(ctx, tx, tenantId, putPayloadOpts) |
2069 | | - |
2070 | | - if err != nil { |
2071 | | - return fmt.Errorf("error putting event payloads: %v", err) |
2072 | | - } |
2073 | | - } |
2074 | | - |
2075 | 2063 | eventExternalIdToId := make(map[pgtype.UUID]int64) |
2076 | 2064 |
|
2077 | 2065 | for _, event := range insertedEvents { |
@@ -2102,73 +2090,33 @@ func (r *OLAPRepositoryImpl) BulkCreateEventsAndTriggers(ctx context.Context, ev |
2102 | 2090 | return fmt.Errorf("error creating event triggers: %v", err) |
2103 | 2091 | } |
2104 | 2092 |
|
2105 | | - if err := commit(ctx); err != nil { |
2106 | | - return fmt.Errorf("error committing transaction: %v", err) |
2107 | | - } |
2108 | | - |
2109 | | - if !r.payloadStore.ExternalStoreEnabled() { |
2110 | | - return nil |
2111 | | - } |
2112 | | - |
2113 | | - offloadToExternalOpts := make([]OffloadToExternalStoreOpts, 0) |
2114 | | - idInsertedAtToExternalId := make(map[IdInsertedAt]pgtype.UUID) |
| 2093 | + tenantIdToPutPayloadOpts := make(map[string][]StoreOLAPPayloadOpts) |
2115 | 2094 |
|
2116 | 2095 | for _, event := range insertedEvents { |
2117 | | - id := event.ID |
2118 | | - insertedAt := event.SeenAt |
2119 | | - idInsertedAtToExternalId[IdInsertedAt{ |
2120 | | - ID: id, |
2121 | | - InsertedAt: insertedAt, |
2122 | | - }] = event.ExternalID |
2123 | | - payload := eventExternalIdToPayload[event.ExternalID] |
2124 | | - |
2125 | | - offloadToExternalOpts = append(offloadToExternalOpts, OffloadToExternalStoreOpts{ |
2126 | | - StorePayloadOpts: &StorePayloadOpts{ |
2127 | | - Id: event.ID, |
2128 | | - InsertedAt: event.SeenAt, |
2129 | | - ExternalId: event.ExternalID, |
2130 | | - Type: sqlcv1.V1PayloadTypeTASKINPUT, |
2131 | | - Payload: payload, |
2132 | | - TenantId: event.TenantID.String(), |
2133 | | - }, |
2134 | | - OffloadAt: time.Now(), |
2135 | | - }) |
2136 | | - } |
2137 | | - |
2138 | | - if len(offloadToExternalOpts) == 0 { |
2139 | | - return nil |
2140 | | - } |
2141 | | - |
2142 | | - retrieveOptsToKey, err := r.PayloadStore().ExternalStore().Store(ctx, offloadToExternalOpts...) |
2143 | | - |
2144 | | - if err != nil { |
2145 | | - return err |
2146 | | - } |
2147 | | - |
2148 | | - tenantIdToffloadOpts := make(map[string][]OffloadPayloadOpts) |
| 2096 | + if event == nil { |
| 2097 | + continue |
| 2098 | + } |
2149 | 2099 |
|
2150 | | - for opt, key := range retrieveOptsToKey { |
2151 | | - externalId := idInsertedAtToExternalId[IdInsertedAt{ |
2152 | | - ID: opt.Id, |
2153 | | - InsertedAt: opt.InsertedAt, |
2154 | | - }] |
| 2100 | + payload := eventExternalIdToPayload[event.ExternalID] |
2155 | 2101 |
|
2156 | | - tenantIdToffloadOpts[opt.TenantId.String()] = append(tenantIdToffloadOpts[opt.TenantId.String()], OffloadPayloadOpts{ |
2157 | | - ExternalId: externalId, |
2158 | | - ExternalLocationKey: string(key), |
| 2102 | + tenantIdToPutPayloadOpts[event.TenantID.String()] = append(tenantIdToPutPayloadOpts[event.TenantID.String()], StoreOLAPPayloadOpts{ |
| 2103 | + Id: event.ID, |
| 2104 | + ExternalId: event.ExternalID, |
| 2105 | + InsertedAt: event.SeenAt, |
| 2106 | + Payload: payload, |
2159 | 2107 | }) |
2160 | 2108 | } |
2161 | 2109 |
|
2162 | | - for tenantId, opts := range tenantIdToffloadOpts { |
2163 | | - err = r.OffloadPayloads(ctx, tenantId, opts) |
| 2110 | + for tenantId, putPayloadOpts := range tenantIdToPutPayloadOpts { |
| 2111 | + err = r.PutPayloads(ctx, tx, tenantId, putPayloadOpts) |
2164 | 2112 |
|
2165 | 2113 | if err != nil { |
2166 | | - return fmt.Errorf("error offloading payloads: %v", err) |
| 2114 | + return fmt.Errorf("error putting event payloads: %v", err) |
2167 | 2115 | } |
2168 | 2116 | } |
2169 | 2117 |
|
2170 | | - if len(offloadToExternalOpts) == 0 { |
2171 | | - return nil |
| 2118 | + if err := commit(ctx); err != nil { |
| 2119 | + return fmt.Errorf("error committing transaction: %v", err) |
2172 | 2120 | } |
2173 | 2121 |
|
2174 | 2122 | return nil |
@@ -2426,27 +2374,107 @@ type OffloadPayloadOpts struct { |
2426 | 2374 | } |
2427 | 2375 |
|
2428 | 2376 | func (r *OLAPRepositoryImpl) PutPayloads(ctx context.Context, tx sqlcv1.DBTX, tenantId string, putPayloadOpts []StoreOLAPPayloadOpts) error { |
2429 | | - insertedAts := make([]pgtype.Timestamptz, len(putPayloadOpts)) |
2430 | | - tenantIds := make([]pgtype.UUID, len(putPayloadOpts)) |
2431 | | - externalIds := make([]pgtype.UUID, len(putPayloadOpts)) |
2432 | | - payloads := make([][]byte, len(putPayloadOpts)) |
2433 | | - locations := make([]string, len(putPayloadOpts)) |
| 2377 | + localTx := false |
| 2378 | + var ( |
| 2379 | + commit func(context.Context) error |
| 2380 | + rollback func() |
| 2381 | + err error |
| 2382 | + ) |
2434 | 2383 |
|
2435 | | - for i, opt := range putPayloadOpts { |
2436 | | - externalIds[i] = opt.ExternalId |
2437 | | - insertedAts[i] = opt.InsertedAt |
2438 | | - tenantIds[i] = sqlchelpers.UUIDFromStr(tenantId) |
2439 | | - payloads[i] = opt.Payload |
2440 | | - locations[i] = string(sqlcv1.V1PayloadLocationOlapINLINE) |
| 2384 | + if tx == nil { |
| 2385 | + localTx = true |
| 2386 | + tx, commit, rollback, err = sqlchelpers.PrepareTx(ctx, r.pool, r.l, 5000) |
| 2387 | + |
| 2388 | + if err != nil { |
| 2389 | + return fmt.Errorf("error beginning transaction in `PutPayload`: %v", err) |
| 2390 | + } |
| 2391 | + |
| 2392 | + defer rollback() |
2441 | 2393 | } |
2442 | 2394 |
|
2443 | | - return r.queries.PutPayloads(ctx, tx, sqlcv1.PutPayloadsParams{ |
2444 | | - Externalids: externalIds, |
2445 | | - Insertedats: insertedAts, |
2446 | | - Tenantids: tenantIds, |
2447 | | - Payloads: payloads, |
2448 | | - Locations: locations, |
| 2395 | + placeholderPayloadType := sqlcv1.V1PayloadTypeTASKEVENTDATA // placeholder, not used in OLAP |
| 2396 | + retrieveOptsToKey := make(map[RetrievePayloadOpts]ExternalPayloadLocationKey) |
| 2397 | + |
| 2398 | + if r.payloadStore.ExternalStoreEnabled() { |
| 2399 | + storeExternalPayloadOpts := make([]OffloadToExternalStoreOpts, len(putPayloadOpts)) |
| 2400 | + |
| 2401 | + for i, opt := range putPayloadOpts { |
| 2402 | + storeOpts := OffloadToExternalStoreOpts{ |
| 2403 | + StorePayloadOpts: &StorePayloadOpts{ |
| 2404 | + Id: opt.Id, |
| 2405 | + InsertedAt: opt.InsertedAt, |
| 2406 | + ExternalId: opt.ExternalId, |
| 2407 | + Type: placeholderPayloadType, |
| 2408 | + Payload: opt.Payload, |
| 2409 | + TenantId: tenantId, |
| 2410 | + }, |
| 2411 | + OffloadAt: opt.InsertedAt.Time, // placeholder, offloaded immediately |
| 2412 | + } |
| 2413 | + |
| 2414 | + storeExternalPayloadOpts[i] = storeOpts |
| 2415 | + } |
| 2416 | + |
| 2417 | + retrieveOptsToKey, err = r.payloadStore.ExternalStore().Store(ctx, storeExternalPayloadOpts...) |
| 2418 | + |
| 2419 | + if err != nil { |
| 2420 | + return fmt.Errorf("error offloading payloads to external store: %v", err) |
| 2421 | + } |
| 2422 | + } |
| 2423 | + |
| 2424 | + insertedAts := make([]pgtype.Timestamptz, 0, len(putPayloadOpts)) |
| 2425 | + tenantIds := make([]pgtype.UUID, 0, len(putPayloadOpts)) |
| 2426 | + externalIds := make([]pgtype.UUID, 0, len(putPayloadOpts)) |
| 2427 | + payloads := make([][]byte, 0, len(putPayloadOpts)) |
| 2428 | + locations := make([]string, 0, len(putPayloadOpts)) |
| 2429 | + externalKeys := make([]string, 0, len(putPayloadOpts)) |
| 2430 | + |
| 2431 | + tenantIdUUID := sqlchelpers.UUIDFromStr(tenantId) |
| 2432 | + |
| 2433 | + for _, opt := range putPayloadOpts { |
| 2434 | + retrieveOpts := RetrievePayloadOpts{ |
| 2435 | + Id: opt.Id, |
| 2436 | + InsertedAt: opt.InsertedAt, |
| 2437 | + Type: placeholderPayloadType, |
| 2438 | + TenantId: tenantIdUUID, |
| 2439 | + } |
| 2440 | + |
| 2441 | + key, ok := retrieveOptsToKey[retrieveOpts] |
| 2442 | + |
| 2443 | + externalIds = append(externalIds, opt.ExternalId) |
| 2444 | + insertedAts = append(insertedAts, opt.InsertedAt) |
| 2445 | + tenantIds = append(tenantIds, tenantIdUUID) |
| 2446 | + |
| 2447 | + if ok { |
| 2448 | + payloads = append(payloads, nil) |
| 2449 | + locations = append(locations, string(sqlcv1.V1PayloadLocationOlapEXTERNAL)) |
| 2450 | + externalKeys = append(externalKeys, string(key)) |
| 2451 | + } else { |
| 2452 | + payloads = append(payloads, opt.Payload) |
| 2453 | + locations = append(locations, string(sqlcv1.V1PayloadLocationOlapINLINE)) |
| 2454 | + externalKeys = append(externalKeys, "") |
| 2455 | + } |
| 2456 | + } |
| 2457 | + |
| 2458 | + err = r.queries.PutPayloads(ctx, tx, sqlcv1.PutPayloadsParams{ |
| 2459 | + Externalids: externalIds, |
| 2460 | + Insertedats: insertedAts, |
| 2461 | + Tenantids: tenantIds, |
| 2462 | + Payloads: payloads, |
| 2463 | + Locations: locations, |
| 2464 | + Externallocationkeys: externalKeys, |
2449 | 2465 | }) |
| 2466 | + |
| 2467 | + if err != nil { |
| 2468 | + return fmt.Errorf("error putting payloads: %v", err) |
| 2469 | + } |
| 2470 | + |
| 2471 | + if localTx { |
| 2472 | + if err := commit(ctx); err != nil { |
| 2473 | + return fmt.Errorf("error committing transaction in `PutPayload`: %v", err) |
| 2474 | + } |
| 2475 | + } |
| 2476 | + |
| 2477 | + return nil |
2450 | 2478 | } |
2451 | 2479 |
|
2452 | 2480 | func (r *OLAPRepositoryImpl) ReadPayload(ctx context.Context, tenantId string, externalId pgtype.UUID) ([]byte, error) { |
|
0 commit comments