Atlas › Test

TestBaseServerOptions

Exact test identity: go.temporal.io/server/temporaltest/TestBaseServerOptions

Package
go.temporal.io/server/temporaltest
Suite / test hierarchy
TestBaseServerOptions
Test
TestBaseServerOptions
Introduced at
endpoint_registry.go ×2 Frontier kind: Joint frontier
Covered ranges
4421
Covered lines
22274
Covered files
603

Covered source

Expand a file to inspect source; the > gutter marks covered lines.

go.temporal.io/server/service/history/shard/context_impl.go 605 covered LOC · 120 ranges

Open complete file

205 )
206
207 > func (s *ContextImpl) String() string { context_impl.go
208 > // constant from initialization, no need for locks
209 > return s.stringRepr
210 > }
211
212 > func (s *ContextImpl) GetShardID() int32 { context_impl.go
213 > // constant from initialization, no need for locks
214 > return s.shardID
215 > }
216
217 func (s *ContextImpl) GetRangeID() int64 {
227 }
228
229 > func (s *ContextImpl) GetExecutionManager() persistence.ExecutionManager { context_impl.go
230 > // constant from initialization, no need for locks
231 > return s.executionManager
232 > }
233
234 > func (s *ContextImpl) GetPingChecks() []pingable.Check { context_impl.go
235 > return []pingable.Check{
236 > {
237 > Name: s.String() + "-shard-lock",
238 > // rwLock may be held for the duration of renewing shard rangeID, which are called with a
239 > // timeout of shardIOTimeout.
240 > Timeout: s.config.ShardIOTimeout() + 30*time.Second,
241 > Ping: func() []pingable.Pingable {
242 > // call rwLock.Lock directly to bypass metrics since this isn't a real request
243 > s.rwLock.Lock()
244 > //nolint:staticcheck // SA2001 just checking if we can acquire the lock
245 > s.rwLock.Unlock()
246 > return nil
247 > },
248 MetricsName: metrics.DDShardLockLatency.Name(),
249 },
253 // of 10 sec.
254 Timeout: 10*time.Second + 30*time.Second,
255 > Ping: func() []pingable.Pingable { context_impl.go
256 > _ = s.ioSemaphore.Acquire(context.Background(), locks.PriorityHigh, 1)
257 > s.ioSemaphore.Release(1)
258 > return nil
259 > },
260 MetricsName: metrics.DDShardIOSemaphoreLatency.Name(),
261 },
265 func (s *ContextImpl) GetEngine(
266 ctx context.Context,
267 > ) (historyi.Engine, error) { context_impl.go
268 > return s.engineFuture.Get(ctx)
269 > }
270
271 func (s *ContextImpl) AssertOwnership(
272 ctx context.Context,
273 > ) error { context_impl.go
274 > if err := s.ioSemaphoreAcquire(ctx); err != nil {
275 return err
276 }
277 > defer s.ioSemaphoreRelease() context_impl.go
278 >
279 > s.wLock()
280 >
281 > // timeout check should be done within the shard lock, in case of shard lock contention
282 > ctx, cancel, err := s.newDetachedContext(ctx)
283 > if err != nil {
284 s.wUnlock()
285 return err
286 }
287 > defer cancel() context_impl.go
288 >
289 > if err := s.errorByState(); err != nil {
290 s.wUnlock()
291 return err
292 }
293
294 > request := &persistence.AssertShardOwnershipRequest{ context_impl.go
295 > ShardID: s.shardID,
296 > RangeID: s.getRangeIDLocked(),
297 > }
298 > s.wUnlock()
299 >
300 > err = s.persistenceShardManager.AssertShardOwnership(ctx, request)
301 > return s.handleWriteError(request.RangeID, err)
302 }
303
349 func (s *ContextImpl) GetQueueExclusiveHighReadWatermark(
350 category tasks.Category,
351 > ) tasks.Key { context_impl.go
352 > s.wLock()
353 > defer s.wUnlock()
354 >
355 > return s.taskKeyManager.getExclusiveReaderHighWatermark(category)
356 > }
357
358 func (s *ContextImpl) GetQueueState(
359 category tasks.Category,
360 > ) (*persistencespb.QueueState, bool) { context_impl.go
361 > s.rLock()
362 > defer s.rUnlock()
363 >
364 > queueState, ok := s.shardInfo.QueueStates[int32(category.ID())]
365 > if !ok {
366 > return nil, false context_impl.go
367 > }
368 // need to make a deep copy, in case UpdateReplicationQueueReaderState does a partial update
369 blob, _ := s.payloadSerializer.QueueStateToBlob(queueState)
525 ctx context.Context,
526 request *persistence.GetHistoryTasksRequest,
527 > ) (*persistence.GetHistoryTasksResponse, error) { context_impl.go
528 > if err := s.errorByState(); err != nil {
529 return nil, err
530 }
531
532 > resp, err := s.executionManager.GetHistoryTasks(ctx, request) context_impl.go
533 > return resp, s.handleReadError(err)
534 }
535
1100 }
1101
1102 > func (s *ContextImpl) GetConfig() *configs.Config { context_impl.go
1103 > // constant from initialization, no need for locks
1104 > return s.config
1105 > }
1106
1107 > func (s *ContextImpl) GetEventsCache() events.Cache { context_impl.go
1108 > // constant from initialization (except for tests), no need for locks
1109 > return s.eventsCache
1110 > }
1111
1112 > func (s *ContextImpl) GetLogger() log.Logger { context_impl.go
1113 > // constant from initialization, no need for locks
1114 > return s.contextTaggedLogger
1115 > }
1116
1117 > func (s *ContextImpl) GetThrottledLogger() log.Logger { context_impl.go
1118 > // constant from initialization, no need for locks
1119 > return s.throttledLogger
1120 > }
1121
1122 > func (s *ContextImpl) getRangeIDLocked() int64 { context_impl.go
1123 > return s.shardInfo.GetRangeId()
1124 > }
1125
1126 > func (s *ContextImpl) errorByState() error { context_impl.go
1127 > s.stateLock.Lock()
1128 > defer s.stateLock.Unlock()
1129 >
1130 > switch s.state {
1131 case contextStateInitialized, contextStateAcquiring:
1132 return ErrShardStatusUnknown
1133 > case contextStateAcquired: context_impl.go
1134 > return nil
1135 case contextStateStopping, contextStateStopped:
1136 return s.newShardClosedErrorWithShardID()
1158 }
1159
1160 > func (s *ContextImpl) renewRangeLocked(isStealing bool) error { context_impl.go
1161 > // We must drain all in-flight requests before updating the rangeID.
1162 > // This is because requests are conditioned on rangeID, if rangeID
1163 > // is updated before draining them, those requests could fail.
1164 > // This also means renew rangeID will be the only in-flight request
1165 > // when it's issued, so it doesn't matter if semaphore is acquired or not
1166 > // before calling this method.
1167 > s.taskKeyManager.drainTaskRequests()
1168 >
1169 > updatedShardInfo := trimShardInfo(s.config, s.clusterMetadata.GetAllClusterInfo(), s.copyShardInfo(s.shardInfo))
1170 > updatedShardInfo.RangeId++
1171 > if isStealing {
1172 > updatedShardInfo.StolenSinceRenew++
1173 > }
1174
1175 > ctx, cancel := s.newIOContext() context_impl.go
1176 > defer cancel()
1177 >
1178 > previousRangeID := s.getRangeIDLocked()
1179 > err := s.persistenceShardManager.UpdateShard(ctx, &persistence.UpdateShardRequest{
1180 > ShardInfo: updatedShardInfo,
1181 > PreviousRangeID: previousRangeID,
1182 > })
1183 > if err != nil {
1184 // Failure in updating shard to grab new RangeID
1185 s.contextTaggedLogger.Error("Persistent store operation failure",
1193
1194 // Range is successfully updated in cassandra now update shard context to reflect new range
1195 > s.contextTaggedLogger.Info("Range updated for shardID", context_impl.go
1196 > tag.ShardRangeID(updatedShardInfo.RangeId),
1197 > tag.PreviousShardRangeID(s.shardInfo.RangeId),
1198 > )
1199 >
1200 > s.shardInfo = trimShardInfo(s.config, s.clusterMetadata.GetAllClusterInfo(), s.copyShardInfo(updatedShardInfo))
1201 > s.taskKeyManager.setRangeID(s.shardInfo.RangeId)
1202 >
1203 > return nil
1204 }
1205
1206 > func (s *ContextImpl) monitorQueueMetrics() { context_impl.go
1207 > timer := time.NewTimer(queueMetricUpdateInterval)
1208 > defer timer.Stop()
1209 >
1210 > done := s.lifecycleCtx.Done()
1211 > for {
1212 > select {
1213 > case <-done: context_impl.go
1214 > return
1215 case <-timer.C:
1216 s.emitShardInfoMetricsLogs()
1350 }
1351
1352 > func (s *ContextImpl) GetCurrentTime(cluster string) time.Time { context_impl.go
1353 > if cluster != s.GetClusterMetadata().GetCurrentClusterName() {
1354 s.wLock()
1355 defer s.wUnlock()
1356 return s.getOrUpdateRemoteClusterInfoLocked(cluster).CurrentTime
1357 }
1358 > return s.timeSource.Now().UTC() context_impl.go
1359 }
1360
1361 > func (s *ContextImpl) getLastUpdatedTime() time.Time { context_impl.go
1362 > s.rLock()
1363 > defer s.rUnlock()
1364 > return s.lastUpdated
1365 > }
1366
1367 > func (s *ContextImpl) handleReadError(err error) error { context_impl.go
1368 > switch err.(type) {
1369 > case nil: context_impl.go
1370 > return nil
1371
1372 case *persistence.ShardOwnershipLostError:
1384 requestRangeID int64,
1385 err error,
1386 > ) error { context_impl.go
1387 > s.wLock()
1388 > defer s.wUnlock()
1389 >
1390 > return s.handleWriteErrorLocked(requestRangeID, err)
1391 > }
1392
1393 func (s *ContextImpl) handleWriteErrorLocked(
1394 requestRangeID int64,
1395 err error,
1396 > ) error { context_impl.go
1397 >
1398 > if requestRangeID != s.getRangeIDLocked() {
1399 return err
1400 }
1401
1402 > if valid := s.IsValid(); !valid { context_impl.go
1403 return err
1404 }
1405 > switch err.(type) { context_impl.go
1406 > case nil: context_impl.go
1407 > // Persistence success: update max read level
1408 > return nil
1409
1410 case *persistence.AppendHistoryTimeoutError:
1442 }
1443
1444 > func (s *ContextImpl) maybeRecordShardAcquisitionLatency(ownershipChanged bool) { context_impl.go
1445 > if ownershipChanged {
1446 > metrics.ShardContextAcquisitionLatency.With(s.GetMetricsHandler()).
1447 > Record(s.GetCurrentTime(s.GetClusterMetadata().GetCurrentClusterName()).Sub(s.getLastUpdatedTime()),
1448 > metrics.OperationTag(metrics.ShardInfoScope),
1449 > )
1450 > }
1451 }
1452
1453 > func (s *ContextImpl) createEngine() historyi.Engine { context_impl.go
1454 > s.contextTaggedLogger.Info("", tag.LifeCycleStarting, tag.ComponentShardEngine)
1455 > engine := s.engineFactory.CreateEngine(s)
1456 > engine.Start()
1457 > s.contextTaggedLogger.Info("", tag.LifeCycleStarted, tag.ComponentShardEngine)
1458 > return engine
1459 > }
1460
1461 // start should only be called by the controller.
1462 > func (s *ContextImpl) start() { context_impl.go
1463 > _ = s.transition(contextRequestAcquire{})
1464 > }
1465
1466 func (s *ContextImpl) UnloadForOwnershipLost() {
1469
1470 // FinishStop should only be called by the controller.
1471 > func (s *ContextImpl) FinishStop() { context_impl.go
1472 > // After this returns, engineFuture.Set may not be called anymore, so if we don't get see
1473 > // an Engine here, we won't ever have one.
1474 > _ = s.transition(contextRequestFinishStop{})
1475 >
1476 > // Use a context that we know is cancelled so that this doesn't block.
1477 > engine, _ := s.engineFuture.Get(s.lifecycleCtx)
1478 >
1479 > // Stop the engine if it was running (outside the lock but before returning).
1480 > if engine != nil {
1481 > s.contextTaggedLogger.Info("", tag.LifeCycleStopping, tag.ComponentShardEngine) context_impl.go
1482 > engine.Stop()
1483 > s.contextTaggedLogger.Info("", tag.LifeCycleStopped, tag.ComponentShardEngine)
1484 > }
1485
1486 // Run finalizer to cleanup any of the shard's associated resources that are registered.
1487 > if s.finalizer != nil { context_impl.go
1488 > s.finalizer.Run(s.config.ShardFinalizerTimeout()) context_impl.go
1489 > }
1490 }
1491
1492 > func (s *ContextImpl) IsValid() bool { context_impl.go
1493 > s.stateLock.Lock()
1494 > defer s.stateLock.Unlock()
1495 > return s.state < contextStateStopping
1496 > }
1497
1498 func (s *ContextImpl) GetLifecycleContext() context.Context {
1506 }
1507
1508 > func (s *ContextImpl) wLock() { context_impl.go
1509 > handler := s.metricsHandler.WithTags(metrics.OperationTag(metrics.ShardInfoScope))
1510 > metrics.LockRequests.With(handler).Record(1)
1511 > startTime := time.Now().UTC()
1512 > defer func() { metrics.LockLatency.With(handler).Record(time.Since(startTime)) }()
1513
1514 > s.rwLock.Lock() context_impl.go
1515 }
1516
1517 > func (s *ContextImpl) rLock() { context_impl.go
1518 > handler := s.metricsHandler.WithTags(metrics.OperationTag(metrics.ShardInfoScope))
1519 > metrics.LockRequests.With(handler).Record(1)
1520 > startTime := time.Now().UTC()
1521 > defer func() { metrics.LockLatency.With(handler).Record(time.Since(startTime)) }()
1522
1523 > s.rwLock.RLock() context_impl.go
1524 }
1525
1526 > func (s *ContextImpl) wUnlock() { context_impl.go
1527 > s.rwLock.Unlock()
1528 > }
1529
1530 > func (s *ContextImpl) rUnlock() { context_impl.go
1531 > s.rwLock.RUnlock()
1532 > }
1533
1534 func (s *ContextImpl) ioSemaphoreAcquire(
1535 ctx context.Context,
1536 > ) (retErr error) { context_impl.go
1537 > priority := locks.PriorityHigh
1538 > callerInfo := headers.GetCallerInfo(ctx)
1539 > if callerInfo.CallerType == headers.CallerTypePreemptable {
1540 priority = locks.PriorityLow
1541 }
1542
1543 > handler := s.metricsHandler.WithTags(metrics.OperationTag(metrics.ShardInfoScope), metrics.PriorityTag(priority)) context_impl.go
1544 > metrics.SemaphoreRequests.With(handler).Record(1)
1545 > startTime := time.Now().UTC()
1546 > defer func() {
1547 > metrics.SemaphoreLatency.With(handler).Record(time.Since(startTime))
1548 > if retErr != nil {
1549 metrics.SemaphoreFailures.With(handler).Record(1)
1550 }
1551 }()
1552
1553 > return s.ioSemaphore.Acquire(ctx, priority, 1) context_impl.go
1554 }
1555
1556 > func (s *ContextImpl) ioSemaphoreRelease() { context_impl.go
1557 > s.ioSemaphore.Release(1)
1558 > }
1559
1560 > func (s *ContextImpl) transition(request contextRequest) error { context_impl.go
1561 > /* State transitions:
1562 >
1563 > The normal pattern:
1564 > Initialized
1565 > controller calls start()
1566 > Acquiring
1567 > acquireShard gets the shard
1568 > Acquired
1569 >
1570 > If we get a transient error from persistence:
1571 > Acquired
1572 > transient error: handleErrorLocked calls transition(contextRequestLost)
1573 > Acquiring
1574 > acquireShard gets the shard
1575 > Acquired
1576 >
1577 > If we get shard ownership lost:
1578 > Acquired
1579 > ShardOwnershipLostError: handleErrorLocked calls transition(contextRequestStop)
1580 > Stopping
1581 > controller removes from map and calls FinishStop()
1582 > Stopped
1583 >
1584 > Stopping can be triggered internally (if we get a ShardOwnershipLostError, or fail to acquire the rangeid
1585 > lock after several minutes) or externally (from controller, e.g. controller shutting down or admin force-
1586 > unload shard). If it's triggered internally, we transition to Stopping, then make an asynchronous callback
1587 > to controller, which will remove us from the map and call FinishStop(), which will transition to Stopped and
1588 > stop the engine. If it's triggered externally, we'll skip over Stopping and go straight to Stopped.
1589 >
1590 > If we transition externally to Stopped, and the acquireShard goroutine is still running, we can't kill it,
1591 > but we should make sure that it can't do anything: the context it uses for persistence ops will be
1592 > canceled, and if it tries to transition states, it will fail.
1593 >
1594 > Invariants:
1595 > - Once state is Stopping, it can only go to Stopped.
1596 > - Once state is Stopped, it can't go anywhere else.
1597 > - At the start of acquireShard, state must be Acquiring.
1598 > - By the end of acquireShard, state must not be Acquiring: either acquireShard set it to Acquired, or the
1599 > controller set it to Stopped.
1600 > - If state is Acquiring, acquireShard should be running in the background.
1601 > - Only acquireShard can use contextRequestAcquired (i.e. transition from Acquiring to Acquired).
1602 > - Once state has reached Acquired at least once, and not reached Stopped, engineFuture must be set.
1603 > - Only the controller may call start() and FinishStop().
1604 > - The controller must call FinishStop() for every ContextImpl it creates.
1605 >
1606 > */
1607 >
1608 > s.stateLock.Lock()
1609 > defer s.stateLock.Unlock()
1610 >
1611 > setStateAcquiring := func() {
1612 > s.state = contextStateAcquiring context_impl.go
1613 > s.contextTaggedLogger.Info("", tag.LifeCycleStarted, tag.ComponentShardContext)
1614 > go s.acquireShard()
1615 > }
1616
1617 > setStateStopping := func(request contextRequestStop) { context_impl.go
1618 s.state = contextStateStopping
1619 s.stopReason = request.reason
1627 }
1628
1629 > setStateStopped := func() { context_impl.go
1630 > s.state = contextStateStopped context_impl.go
1631 > s.contextTaggedLogger.Info("", tag.LifeCycleStopped, tag.ComponentShardContext)
1632 > // Do this again in case we skipped the stopping state, which could happen
1633 > // when calling CloseShardByID or the controller is shutting down.
1634 > s.lifecycleCancel()
1635 > }
1636
1637 > switch s.state { context_impl.go
1638 > case contextStateInitialized: context_impl.go
1639 > switch request := request.(type) {
1640 > case contextRequestAcquire:
1641 > setStateAcquiring()
1642 > return nil
1643 case contextRequestStop:
1644 setStateStopping(request)
1648 return nil
1649 }
1650 > case contextStateAcquiring: context_impl.go
1651 > switch request := request.(type) {
1652 case contextRequestAcquire:
1653 return nil // nothing to do, already acquiring
1654 > case contextRequestAcquired: context_impl.go
1655 > s.state = contextStateAcquired
1656 > if request.engine != nil {
1657 > // engineFuture.Set should only be called inside stateLock when state is context_impl.go
1658 > // Acquiring, so that other code (i.e. FinishStop) can know that after a state
1659 > // transition to Stopping/Stopped, engineFuture cannot be Set.
1660 > if s.engineFuture.Ready() {
1661 // defensive check, this should never happen
1662 s.contextTaggedLogger.Warn("transition to acquired with engine set twice")
1663 return errInvalidTransition
1664 }
1665 > s.engineFuture.Set(request.engine, nil) context_impl.go
1666 }
1667 > if !s.engineFuture.Ready() { context_impl.go
1668 // we should either have an engine from a previous transition, or set one now
1669 s.contextTaggedLogger.Warn("transition to acquired but no engine set")
1671 }
1672
1673 > return nil context_impl.go
1674 case contextRequestLost:
1675 return nil // nothing to do, already acquiring
1681 return nil
1682 }
1683 > case contextStateAcquired: context_impl.go
1684 > switch request := request.(type) {
1685 case contextRequestAcquire:
1686 return nil // nothing to do, already acquired
1691 setStateStopping(request)
1692 return nil
1693 > case contextRequestFinishStop: context_impl.go
1694 > setStateStopped()
1695 > return nil
1696 }
1697 case contextStateStopping:
1720 // notifyQueueProcessor sends notification to all queue processors for triggering a load
1721 // NOTE: this method assumes engineFuture is already in a ready state.
1722 > func (s *ContextImpl) notifyQueueProcessor() { context_impl.go
1723 > // use a cancelled ctx so the method won't be blocked if engineFuture is not ready
1724 > cancelledCtx, cancel := context.WithCancel(context.Background())
1725 > cancel()
1726 >
1727 > // we will get the engine when the Future is ready
1728 > engine, err := s.engineFuture.Get(cancelledCtx)
1729 > if err != nil {
1730 s.contextTaggedLogger.Warn("tried to notify queue processor when engine is not ready")
1731 return
1732 }
1733
1734 > now := s.timeSource.Now() context_impl.go
1735 > fakeTasks := make(map[tasks.Category][]tasks.Task)
1736 > for _, category := range s.taskCategoryRegistry.GetCategories() {
1737 > fakeTasks[category] = []tasks.Task{tasks.NewFakeTask(definition.WorkflowKey{}, category, now)}
1738 > }
1739
1740 > engine.NotifyNewTasks(fakeTasks) context_impl.go
1741 }
1742
1743 > func (s *ContextImpl) updateHandoverNamespacePendingTaskID() { context_impl.go
1744 > s.wLock()
1745 >
1746 > if s.errorByState() != nil {
1747 // if not in acquired state, this function will be called again
1748 // later when shard is re-acquired.
1751 }
1752
1753 > maxReplicationTaskID := s.getMaxReplicationTaskID() context_impl.go
1754 > s.handoverTracker.ResolvePendingTaskIDs(maxReplicationTaskID)
1755 > s.wUnlock()
1756 >
1757 > s.notifyReplicationQueueProcessor(maxReplicationTaskID)
1758 }
1759
1760 > func (s *ContextImpl) getMaxReplicationTaskID() int64 { context_impl.go
1761 > return s.taskKeyManager.getExclusiveReaderHighWatermark(tasks.CategoryReplication).TaskID - 1
1762 > }
1763
1764 > func (s *ContextImpl) notifyReplicationQueueProcessor(taskID int64) { context_impl.go
1765 > // Replication ack level won't exceed the max taskID it received via task notification.
1766 > // Since here we want it's ack level to advance to at least the input taskID, we need to
1767 > // trigger an fake notification.
1768 >
1769 > cancelledCtx, cancel := context.WithCancel(context.Background())
1770 > cancel()
1771 >
1772 > engine, err := s.engineFuture.Get(cancelledCtx)
1773 > if err != nil {
1774 s.contextTaggedLogger.Warn("tried to notify replication queue processor when engine is not ready")
1775 return
1776 }
1777
1778 > fakeReplicationTask := tasks.NewFakeTask(definition.WorkflowKey{}, tasks.CategoryReplication, tasks.MinimumKey.FireTime) context_impl.go
1779 > fakeReplicationTask.SetTaskID(taskID)
1780 >
1781 > engine.NotifyNewTasks(map[tasks.Category][]tasks.Task{
1782 > tasks.CategoryReplication: {fakeReplicationTask},
1783 > })
1784 }
1785
1786 > func (s *ContextImpl) loadShardMetadata(ownershipChanged *bool) error { context_impl.go
1787 > // Only have to do this once, we can just re-acquire the rangeid lock after that
1788 > s.rLock()
1789 > if s.shardInfo != nil {
1790 s.rUnlock()
1791 return nil
1792 }
1793 > s.rUnlock() context_impl.go
1794 >
1795 > // We don't have any shardInfo yet, load it (outside of context rwlock)
1796 > ctx, cancel := s.newIOContext()
1797 > defer cancel()
1798 > resp, err := s.persistenceShardManager.GetOrCreateShard(ctx, &persistence.GetOrCreateShardRequest{
1799 > ShardID: s.shardID,
1800 > LifecycleContext: s.lifecycleCtx,
1801 > })
1802 > if err != nil {
1803 s.contextTaggedLogger.Error("Failed to load shard", tag.Error(err))
1804 return err
1805 }
1806 > *ownershipChanged = resp.ShardInfo.Owner != s.owner context_impl.go
1807 > shardInfo := trimShardInfo(s.config, s.clusterMetadata.GetAllClusterInfo(), s.copyShardInfo(resp.ShardInfo))
1808 > shardInfo.Owner = s.owner
1809 >
1810 > // initialize the cluster current time to be the same as ack level
1811 > remoteClusterInfos := make(map[string]*remoteClusterInfo)
1812 > var taskMinScheduledTime time.Time
1813 > currentClusterName := s.GetClusterMetadata().GetCurrentClusterName()
1814 > taskCategories := s.taskCategoryRegistry.GetCategories()
1815 > for clusterName, info := range s.GetClusterMetadata().GetAllClusterInfo() {
1816 > if !info.Enabled {
1817 continue
1818 }
1819
1820 > exclusiveMaxReadTime := tasks.DefaultFireTime context_impl.go
1821 > for categoryID, queueState := range shardInfo.QueueStates {
1822 category, ok := taskCategories[int(categoryID)]
1823 if !ok || category.Type() != tasks.CategoryTypeScheduled {
1833 // Once we validate the rest of the code can worker correctly with higher precision, the code should simply be
1834 // taskMinScheduledTime = util.MaxTime(taskMinScheduledTime, maxReadTime)
1835 > taskMinScheduledTime = util.MaxTime( context_impl.go
1836 > taskMinScheduledTime,
1837 > exclusiveMaxReadTime.Add(common.ScheduledTaskMinPrecision).Truncate(common.ScheduledTaskMinPrecision),
1838 > )
1839 >
1840 > if clusterName != currentClusterName {
1841 remoteClusterInfos[clusterName] = &remoteClusterInfo{
1842 CurrentTime: exclusiveMaxReadTime,
1847 }
1848
1849 > s.wLock() context_impl.go
1850 > defer s.wUnlock()
1851 >
1852 > s.shardInfo = shardInfo
1853 > s.remoteClusterInfos = remoteClusterInfos
1854 > s.taskKeyManager.setTaskMinScheduledTime(taskMinScheduledTime)
1855 >
1856 > return nil
1857 }
1858
1920 }
1921
1922 > func (s *ContextImpl) acquireShard() { context_impl.go
1923 > // This is called in two contexts: initially acquiring the rangeid lock, and trying to
1924 > // re-acquire it after a persistence error. In both cases, we retry the acquire operation
1925 > // (renewRangeLocked) for 5 minutes. Each individual attempt uses shardIOTimeout (by default, 5s) as
1926 > // the timeout. This lets us handle a few minutes of persistence unavailability without
1927 > // dropping and reloading the whole shard context, which is relatively expensive (includes
1928 > // caches that would have to be refilled, etc.).
1929 > //
1930 > // We stop retrying on any of:
1931 > // 1. We succeed in acquiring the rangeid lock.
1932 > // 2. We get ShardOwnershipLostError or lifecycleCtx ended.
1933 > // 3. The state changes to Stopping or Stopped.
1934 > //
1935 > // If the shard controller sees that service resolver has assigned ownership to someone
1936 > // else, it will call FinishStop, which will trigger case 3 above, and also cancel
1937 > // lifecycleCtx. The persistence operations called here use lifecycleCtx as their context,
1938 > // so if we were blocked in any of them, they should return immediately with a context
1939 > // canceled error.
1940 > policy := s.acquireShardRetryPolicy
1941 > if policy == nil {
1942 > policy = backoff.NewExponentialRetryPolicy(1 * time.Second).WithExpirationInterval(5 * time.Minute) context_impl.go
1943 > }
1944
1945 // Remember this value across attempts
1946 > ownershipChanged := false context_impl.go
1947 >
1948 > op := func() error {
1949 > if !s.IsValid() {
1950 return s.newShardClosedErrorWithShardID()
1951 }
1952
1953 // Initial load of shard metadata
1954 > err := s.loadShardMetadata(&ownershipChanged) context_impl.go
1955 > if err != nil {
1956 return err
1957 }
1967 // in-flight requests before making the call. So it's guaranteed that the renew rangeID
1968 // UpdateShard call is the only one in flight.
1969 > s.wLock() context_impl.go
1970 > err = s.renewRangeLocked(true)
1971 > s.wUnlock()
1972 > if err != nil {
1973 return err
1974 }
1975
1976 > s.contextTaggedLogger.Info("Acquired shard") context_impl.go
1977 >
1978 > // The first time we get the shard, we have to create the engine
1979 > var engine historyi.Engine
1980 > if !s.engineFuture.Ready() {
1981 > s.maybeRecordShardAcquisitionLatency(ownershipChanged) context_impl.go
1982 > engine = s.createEngine()
1983 > }
1984
1985 // NOTE: engine is created & started before setting shard state to acquired.
1987 // -> information for handover namespace is recorded before shard can servce traffic
1988 // -> upon shard reload, no history api or task can go through for ns in handover state
1989 > err = s.transition(contextRequestAcquired{engine: engine}) context_impl.go
1990 >
1991 > if err != nil {
1992 if engine != nil {
1993 // We tried to set the engine but the context was already stopped
1999 // we know engineFuture must be ready here, and we can notify queue processor
2000 // to trigger a load as queue max level can be updated to a newer value
2001 > s.notifyQueueProcessor() context_impl.go
2002 > // This runs until the lifecycleCtx is cancelled, so we only need to start it once
2003 > s.queueMetricEmitter.Do(func() {
2004 > go s.monitorQueueMetrics()
2005 > })
2006
2007 > s.updateHandoverNamespacePendingTaskID() context_impl.go
2008 >
2009 > return nil
2010 }
2011
2012 // keep retrying except ShardOwnershipLostError or lifecycle context ended
2013 > acquireShardRetryable := func(err error) (isRetryable bool) { context_impl.go
2014 defer func() {
2015 s.contextTaggedLogger.Error(
2028 return true
2029 }
2030 > err := backoff.ThrottleRetry(op, policy, acquireShardRetryable) context_impl.go
2031 > if err != nil {
2032 // We got an non-retryable error, e.g. ShardOwnershipLostError
2033 s.contextTaggedLogger.Error("Couldn't acquire shard", tag.Error(err))
2072 endpointRegistry chasm.EndpointRegistry,
2073 handoverTrackerFactory HandoverTrackerFactory,
2074 > ) (*ContextImpl, error) { context_impl.go
2075 > hostIdentity := hostInfoProvider.HostInfo().Identity()
2076 > sequenceID := atomic.AddInt64(&shardContextSequenceID, 1)
2077 >
2078 > lifecycleCtx, lifecycleCancel := context.WithCancel(context.Background())
2079 >
2080 > ioConcurrency := historyConfig.ShardIOConcurrency()
2081 > if ioConcurrency != 1 && persistenceConfig.DataStores[persistenceConfig.DefaultStore].Cassandra != nil {
2082 throttledLogger.Warn(
2083 fmt.Sprintf("Cassandra persistence implementation only supports %v == 1", dynamicconfig.ShardIOConcurrency),
2087 }
2088
2089 > taggedLogger := log.With(logger, tag.ShardID(shardID), tag.Address(hostIdentity)) context_impl.go
2090 > shardContext := &ContextImpl{
2091 > state: contextStateInitialized,
2092 > shardID: shardID,
2093 > owner: fmt.Sprintf("%s-%v-%v", hostIdentity, sequenceID, uuid.NewString()),
2094 > stringRepr: fmt.Sprintf("Shard(%d)", shardID),
2095 > executionManager: persistenceExecutionManager,
2096 > metricsHandler: metricsHandler,
2097 > eventLogger: eventLogger,
2098 > closeCallback: closeCallback,
2099 > config: historyConfig,
2100 > finalizer: finalizer.New(taggedLogger, metricsHandler),
2101 > contextTaggedLogger: taggedLogger,
2102 > throttledLogger: log.With(throttledLogger, tag.ShardID(shardID), tag.Address(hostIdentity)),
2103 > engineFactory: factory,
2104 > persistenceShardManager: persistenceShardManager,
2105 > clientBean: clientBean,
2106 > historyClient: historyClient,
2107 > payloadSerializer: payloadSerializer,
2108 > timeSource: timeSource,
2109 > namespaceRegistry: namespaceRegistry,
2110 > saProvider: saProvider,
2111 > saMapperProvider: saMapperProvider,
2112 > clusterMetadata: clusterMetadata,
2113 > archivalMetadata: archivalMetadata,
2114 > hostInfoProvider: hostInfoProvider,
2115 > taskCategoryRegistry: taskCategoryRegistry,
2116 > lifecycleCtx: lifecycleCtx,
2117 > lifecycleCancel: lifecycleCancel,
2118 > engineFuture: future.NewFuture[historyi.Engine](),
2119 > queueMetricEmitter: sync.Once{},
2120 > ioSemaphore: locks.NewPrioritySemaphore(ioConcurrency),
2121 > stateMachineRegistry: stateMachineRegistry,
2122 > chasmRegistry: chasmRegistry,
2123 > chasmWorkflowRegistry: chasmWorkflowRegistry,
2124 > endpointRegistry: endpointRegistry,
2125 > businessIDRateLimiters: cache.New(
2126 > historyConfig.BusinessIDReuseLimiterCacheSize(),
2127 > &cache.Options{TTL: historyConfig.BusinessIDReuseLimiterCacheTTL()},
2128 > ),
2129 > }
2130 > shardContext.taskKeyManager = newTaskKeyManager(
2131 > shardContext.taskCategoryRegistry,
2132 > timeSource,
2133 > historyConfig,
2134 > shardContext.GetLogger(),
2135 > func() error {
2136 return shardContext.renewRangeLocked(false)
2137 },
2138 )
2139 > shardContext.handoverTracker = handoverTrackerFactory(HandoverTrackerParams{ context_impl.go
2140 > ClusterMetadata: clusterMetadata,
2141 > GetMaxReplicationTaskID: shardContext.getMaxReplicationTaskID,
2142 > ErrorByStateFn: shardContext.errorByState,
2143 > NotifyReplicationFn: shardContext.notifyReplicationQueueProcessor,
2144 > NamespaceRegistry: namespaceRegistry,
2145 > Logger: taggedLogger,
2146 > })
2147 > if shardContext.GetConfig().EnableHostLevelEventsCache() {
2148 shardContext.eventsCache = eventsCache
2149 > } else { context_impl.go
2150 > shardContext.eventsCache = events.NewShardLevelEventsCache(
2151 > shardContext.executionManager,
2152 > shardContext.config,
2153 > shardContext.metricsHandler,
2154 > shardContext.contextTaggedLogger,
2155 > false,
2156 > )
2157 > }
2158 > shardContext.initLastUpdatesTime()
2159 > return shardContext, nil
2160 }
2161
2162 > func (s *ContextImpl) initLastUpdatesTime() { context_impl.go
2163 > // We need to set lastUpdate time to "now" - "wait between shard updates time" + "first update interval".
2164 > // This is done to make sure that first shard update` will happen around "first update interval" after "now".
2165 > // The idea is to allow queue to persist even in the case of (relativly) constantly
2166 > // moving shards between hosts.
2167 > // Note: it still may prevent queue from progressing if shard moving rate is too high
2168 > lastUpdated := s.timeSource.Now()
2169 > lastUpdated = lastUpdated.Add(-1 * s.config.ShardUpdateMinInterval())
2170 > lastUpdated = lastUpdated.Add(s.config.ShardFirstUpdateInterval())
2171 > s.lastUpdated = lastUpdated
2172 > }
2173
2174 // TODO: why do we need a deep copy here?
2175 > func (s *ContextImpl) copyShardInfo(shardInfo *persistencespb.ShardInfo) *persistencespb.ShardInfo { context_impl.go
2176 > // need to ser/de to make a deep copy of queue state
2177 > queueStates := make(map[int32]*persistencespb.QueueState, len(shardInfo.QueueStates))
2178 > for k, v := range shardInfo.QueueStates {
2179 blob, _ := s.payloadSerializer.QueueStateToBlob(v)
2180 queueState, _ := s.payloadSerializer.QueueStateFromBlob(blob)
2182 }
2183
2184 > return &persistencespb.ShardInfo{ context_impl.go
2185 > ShardId: shardInfo.ShardId,
2186 > Owner: shardInfo.Owner,
2187 > RangeId: shardInfo.RangeId,
2188 > StolenSinceRenew: shardInfo.StolenSinceRenew,
2189 > ReplicationDlqAckLevel: maps.Clone(shardInfo.ReplicationDlqAckLevel),
2190 > UpdateTime: shardInfo.UpdateTime,
2191 > QueueStates: queueStates,
2192 > }
2193 }
2194
2197 }
2198
2199 > func (s *ContextImpl) GetPayloadSerializer() serialization.Serializer { context_impl.go
2200 > return s.payloadSerializer
2201 > }
2202
2203 func (s *ContextImpl) GetHistoryClient() historyservice.HistoryServiceClient {
2212 }
2213
2214 > func (s *ContextImpl) GetMetricsHandler() metrics.Handler { context_impl.go
2215 > return s.metricsHandler
2216 > }
2217
2218 > func (s *ContextImpl) GetTimeSource() cclock.TimeSource { context_impl.go
2219 > return s.timeSource
2220 > }
2221
2222 > func (s *ContextImpl) GetNamespaceRegistry() namespace.Registry { context_impl.go
2223 > return s.namespaceRegistry
2224 > }
2225
2226 > func (s *ContextImpl) GetSearchAttributesProvider() searchattribute.Provider { context_impl.go
2227 > return s.saProvider
2228 > }
2229
2230 > func (s *ContextImpl) GetSearchAttributesMapperProvider() searchattribute.MapperProvider { context_impl.go
2231 > return s.saMapperProvider
2232 > }
2233
2234 > func (s *ContextImpl) GetClusterMetadata() cluster.Metadata { context_impl.go
2235 > return s.clusterMetadata
2236 > }
2237
2238 func (s *ContextImpl) GetArchivalMetadata() archiver.ArchivalMetadata {
2240 }
2241
2242 > func (s *ContextImpl) StateMachineRegistry() *hsm.Registry { context_impl.go
2243 > return s.stateMachineRegistry
2244 > }
2245
2246 func (s *ContextImpl) ChasmRegistry() *chasm.Registry {
2248 }
2249
2250 > func (s *ContextImpl) ChasmWorkflowRegistry() *chasmworkflow.Registry { context_impl.go
2251 > return s.chasmWorkflowRegistry
2252 > }
2253
2254 func (s *ContextImpl) EndpointRegistry() chasm.EndpointRegistry {
2303 func (s *ContextImpl) newDetachedContext(
2304 ctx context.Context,
2305 > ) (context.Context, context.CancelFunc, error) { context_impl.go
2306 > if err := ctx.Err(); err != nil {
2307 return nil, nil, err
2308 }
2309
2310 > detachedContext := rpc.CopyContextValues(s.lifecycleCtx, ctx) context_impl.go
2311 >
2312 > var cancel context.CancelFunc
2313 > deadline, ok := ctx.Deadline()
2314 > if ok {
2315 timeout := max(deadline.Sub(s.GetTimeSource().Now()), minContextTimeout)
2316 detachedContext, cancel = context.WithTimeout(detachedContext, timeout)
2317 > } else { context_impl.go
2318 > cancel = func() {} context_impl.go
2319 }
2320
2321 > return detachedContext, cancel, nil context_impl.go
2322 }
2323
2324 > func (s *ContextImpl) newIOContext() (context.Context, context.CancelFunc) { context_impl.go
2325 > ctx, cancel := context.WithTimeout(s.lifecycleCtx, s.config.ShardIOTimeout())
2326 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
2327 >
2328 > return ctx, cancel
2329 > }
2330
2331 // newShardClosedErrorWithShardID when shard is closed and a req cannot be processed
2341 allClusterInfo map[string]cluster.ClusterInformation,
2342 shardInfo *persistencespb.ShardInfo,
2343 > ) *persistencespb.ShardInfo { context_impl.go
2344 > if shardInfo.QueueStates != nil && shardInfo.QueueStates[int32(tasks.CategoryIDReplication)] != nil {
2345 for readerID := range shardInfo.QueueStates[int32(tasks.CategoryIDReplication)].ReaderStates {
2346 clusterID, _ := ReplicationReaderIDToClusterShardID(readerID)
go.temporal.io/server/service/frontend/fx.go 512 covered LOC · 54 ranges

Open complete file

110 fx.Provide(AuthorizationInterceptorProvider),
111 fx.Provide(NamespaceCheckerProvider),
112 > fx.Provide(func(so GrpcServerOptions) *grpc.Server { return grpc.NewServer(so.Options...) }), fx.go
113 fx.Provide(callbackValidatorProvider),
114 fx.Provide(HandlerProvider),
154 metricsHandler metrics.Handler,
155 membershipMonitor membership.Monitor,
156 > ) *Service { fx.go
157 > return NewService(
158 > serviceConfig,
159 > server,
160 > healthServer,
161 > httpAPIServer,
162 > handler,
163 > adminHandler,
164 > operatorHandler,
165 > versionChecker,
166 > visibilityMgr,
167 > logger,
168 > grpcListener,
169 > metricsHandler,
170 > membershipMonitor,
171 > )
172 > }
173
174 // GrpcServerOptions are the options to build the frontend gRPC server along
189 audienceGetter authorization.JWTAudienceMapper,
190 dc *dynamicconfig.Collection,
191 > ) *authorization.Interceptor { fx.go
192 > return authorization.NewInterceptor(
193 > claimMapper,
194 > authorizer,
195 > metricsHandler,
196 > logger,
197 > namespaceChecker,
198 > audienceGetter,
199 > cfg.Global.Authorization.AuthHeaderName,
200 > cfg.Global.Authorization.AuthExtraHeaderName,
201 > serviceConfig.ExposeAuthorizerErrors,
202 > dynamicconfig.EnableCrossNamespaceCommands.Get(dc),
203 > dynamicconfig.EnablePrincipalPropagation.Get(dc),
204 > dynamicconfig.DisableStreamingAuthorizer.Get(dc),
205 > )
206 > }
207
208 > func NamespaceCheckerProvider(registry namespace.Registry) authorization.NamespaceChecker { fx.go
209 > return &namespaceChecker{r: registry}
210 > }
211
212 > func (n *namespaceChecker) Exists(name namespace.Name) error { fx.go
213 > // This will get called before the namespace state validation interceptor. We want to
214 > // disable readthrough to avoid polluting the negative lookup cache, e.g. if this call is
215 > // for RegisterNamespace and the namespace doesn't exist yet.
216 > opts := namespace.GetNamespaceOptions{DisableReadthrough: true}
217 > _, err := n.r.GetNamespaceWithOptions(name, opts)
218 > return err
219 > }
220
221 func GrpcServerOptionsProvider(
249 customStreamInterceptors []grpc.StreamServerInterceptor,
250 metricsHandler metrics.Handler,
251 > ) GrpcServerOptions { fx.go
252 > kep := keepalive.EnforcementPolicy{
253 > MinTime: serviceConfig.KeepAliveMinTime(),
254 > PermitWithoutStream: serviceConfig.KeepAlivePermitWithoutStream(),
255 > }
256 > kp := keepalive.ServerParameters{
257 > MaxConnectionIdle: serviceConfig.KeepAliveMaxConnectionIdle(),
258 > MaxConnectionAge: serviceConfig.KeepAliveMaxConnectionAge(),
259 > MaxConnectionAgeGrace: serviceConfig.KeepAliveMaxConnectionAgeGrace(),
260 > Time: serviceConfig.KeepAliveTime(),
261 > Timeout: serviceConfig.KeepAliveTimeout(),
262 > }
263 > var grpcServerOptions []grpc.ServerOption
264 > var err error
265 > switch serviceName {
266 > case primitives.FrontendService:
267 > grpcServerOptions, err = rpcFactory.GetFrontendGRPCServerOptions()
268 case primitives.InternalFrontendService:
269 grpcServerOptions, err = rpcFactory.GetInternodeGRPCServerOptions()
271 err = fmt.Errorf("unexpected frontend service name %q", serviceName)
272 }
273 > if err != nil { fx.go
274 logger.Fatal("creating gRPC server options failed", tag.Error(err))
275 }
276 > unaryInterceptors := []grpc.UnaryServerInterceptor{ fx.go
277 > // Order of interceptors is important
278 > // Mask error interceptor should be the most outer interceptor since it handle the errors format
279 > // Service Error Interceptor should be the next most outer interceptor on error handling
280 > maskInternalErrorDetailsInterceptor.Intercept,
281 > serviceErrorInterceptor.Intercept,
282 > interceptor.NewFrontendServiceErrorInterceptor(logger),
283 > // BusinessID interceptor extracts business ID and adds it to context for use, must be before any interceptor that touches namespaces (namespaceValidator, handoverInterceptor)
284 > businessIDInterceptor.Intercept,
285 > namespaceValidatorInterceptor.NamespaceValidateIntercept,
286 > namespaceLogInterceptor.Intercept, // TODO: Deprecate this with a outer custom interceptor
287 > metrics.NewServerMetricsContextInjectorInterceptor(),
288 > authInterceptor.Intercept,
289 > // Handover interceptor has to above redirection because the request will route to the correct cluster after handover completed.
290 > // And retry cannot be performed before customInterceptors.
291 > namespaceHandoverInterceptor.Intercept,
292 > redirectionInterceptor.Intercept,
293 > // Telemetry interceptor must be after redirection to ensure metrics are recorded in the correct cluster
294 > telemetryInterceptor.UnaryIntercept,
295 > healthInterceptor.Intercept,
296 > namespaceValidatorInterceptor.StateValidationIntercept,
297 > namespaceCountLimiterInterceptor.Intercept,
298 > namespaceRateLimiterInterceptor.Intercept,
299 > rateLimitInterceptor.Intercept,
300 > sdkVersionInterceptor.Intercept,
301 > callerInfoInterceptor.Intercept,
302 > slowRequestLoggerInterceptor.Intercept,
303 > chasmRequestVisibilityInterceptor.Intercept,
304 > contextMetadataInterceptor.Intercept,
305 > }
306 > if len(customInterceptors) > 0 {
307 // TODO: Deprecate WithChainedFrontendGrpcInterceptors and provide a inner custom interceptor
308 unaryInterceptors = append(unaryInterceptors, customInterceptors...)
309 }
310 // retry interceptor should be the most inner interceptor
311 > unaryInterceptors = append(unaryInterceptors, retryableInterceptor.Intercept) fx.go
312 >
313 > streamInterceptor := []grpc.StreamServerInterceptor{
314 > authInterceptor.InterceptStream,
315 > telemetryInterceptor.StreamIntercept,
316 > }
317 > if len(customStreamInterceptors) > 0 {
318 streamInterceptor = append(streamInterceptor, customStreamInterceptors...)
319 }
320
321 > grpcServerOptions = append( fx.go
322 > grpcServerOptions,
323 > grpc.KeepaliveParams(kp),
324 > grpc.KeepaliveEnforcementPolicy(kep),
325 > grpc.ChainUnaryInterceptor(unaryInterceptors...),
326 > grpc.ChainStreamInterceptor(streamInterceptor...),
327 > )
328 >
329 > multiStats := rpc.MultiStatsHandler{}
330 > if traceStatsHandler != nil {
331 multiStats = append(multiStats, traceStatsHandler)
332 }
333 > if metricsStatsHandler != nil { fx.go
334 > multiStats = append(multiStats, metricsStatsHandler)
335 > }
336 > if len(multiStats) > 0 {
337 > grpcServerOptions = append(grpcServerOptions, grpc.StatsHandler(multiStats))
338 > }
339 > return GrpcServerOptions{Options: grpcServerOptions, UnaryInterceptors: unaryInterceptors}
340 }
341
343 dc *dynamicconfig.Collection,
344 persistenceConfig config.Persistence,
345 > ) *Config { fx.go
346 > return NewConfig(
347 > dc,
348 > persistenceConfig.NumHistoryShards,
349 > )
350 > }
351
352 func ServiceErrorInterceptorProvider(
353 dc *dynamicconfig.Collection,
354 > ) *interceptor.ServiceErrorInterceptor { fx.go
355 > return interceptor.NewServiceErrorInterceptor(
356 > dynamicconfig.MaxServiceErrorMessageLength.Get(dc),
357 > )
358 > }
359
360 > func ThrottledLoggerRpsFnProvider(serviceConfig *Config) resource.ThrottledLoggerRpsFn { fx.go
361 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
362 }
363
365 namespaceLogger resource.NamespaceLogger,
366 namespaceRegistry namespace.Registry,
367 > ) *interceptor.NamespaceLogInterceptor { fx.go
368 > return interceptor.NewNamespaceLogInterceptor(
369 > namespaceRegistry,
370 > namespaceLogger)
371 > }
372
373 > func RetryableInterceptorProvider() *interceptor.RetryableInterceptor { fx.go
374 > return interceptor.NewRetryableInterceptor(
375 > common.CreateFrontendHandlerRetryPolicy(),
376 > common.IsServiceHandlerRetryableError,
377 > )
378 > }
379
380 func RedirectionInterceptorProvider(
387 timeSource clock.TimeSource,
388 clusterMetadata cluster.Metadata,
389 > ) *interceptor.Redirection { fx.go
390 > return interceptor.NewRedirection(
391 > configuration.EnableNamespaceNotActiveAutoForwarding,
392 > configuration.ForceNamespaceSelectedAPIAutoForwarding,
393 > namespaceCache,
394 > policy,
395 > logger,
396 > clientBean,
397 > metricsHandler,
398 > timeSource,
399 > clusterMetadata,
400 > )
401 > }
402
403 func BusinessIDInterceptorProvider(
404 extractor interceptor.RoutingKeyExtractor,
405 logger log.Logger,
406 > ) *interceptor.RoutingKeyInterceptor { fx.go
407 > return interceptor.NewRoutingKeyInterceptor(
408 > []interceptor.RoutingKeyExtractorFunc{
409 > interceptor.WorkflowServiceExtractor(extractor),
410 > },
411 > logger,
412 > )
413 > }
414
415 type NamespaceHandoverInterceptorParams struct {
426 func NamespaceHandoverInterceptorProvider(
427 params NamespaceHandoverInterceptorParams,
428 > ) *interceptor.NamespaceHandoverInterceptor { fx.go
429 > return interceptor.NewNamespaceHandoverInterceptor(
430 > params.DynamicConfig,
431 > params.NamespaceRegistry,
432 > params.MetricsHandler,
433 > params.Logger,
434 > params.TimeSource,
435 > params.RequestErrorHandler,
436 > params.AdditionalAllowedMethodsDuringHandover,
437 > )
438 > }
439
440 func ErrorHandlerProvider(
441 logger log.Logger,
442 serviceConfig *Config,
443 > ) *interceptor.RequestErrorHandler { fx.go
444 > return interceptor.NewRequestErrorHandler(
445 > logger,
446 > serviceConfig.LogAllReqErrors,
447 > )
448 > }
449
450 func TelemetryInterceptorProvider(
454 serviceConfig *Config,
455 requestErrorHandler *interceptor.RequestErrorHandler,
456 > ) *interceptor.TelemetryInterceptor { fx.go
457 > return interceptor.NewTelemetryInterceptor(
458 > namespaceRegistry,
459 > metricsHandler,
460 > logger,
461 > serviceConfig.LogAllReqErrors,
462 > requestErrorHandler,
463 > )
464 > }
465
466 > func getRateFnWithMetrics(rateFn quotas.RateFn, handler metrics.Handler) quotas.RateFn { fx.go
467 > return func() float64 {
468 > rate := rateFn()
469 > metrics.HostRPSLimit.With(handler).Record(rate)
470 > return rate
471 > }
472 }
473
477 handler metrics.Handler,
478 logger log.SnTaggedLogger,
479 > ) *interceptor.RateLimitInterceptor { fx.go
480 > rateFn := calculator.NewLoggedCalculator(
481 > calculator.ClusterAwareQuotaCalculator{
482 > MemberCounter: frontendServiceResolver,
483 > PerInstanceQuota: serviceConfig.RPS,
484 > GlobalQuota: serviceConfig.GlobalRPS,
485 > },
486 > log.With(logger, tag.ComponentRPCHandler, tag.ScopeHost),
487 > ).GetQuota
488 > rateFnWithMetrics := getRateFnWithMetrics(rateFn, handler)
489 >
490 > namespaceReplicationInducingRateFn := func() float64 {
491 > return float64(serviceConfig.NamespaceReplicationInducingAPIsRPS())
492 > }
493
494 > return interceptor.NewRateLimitInterceptor( fx.go
495 > configs.NewRequestToRateLimiter(
496 > quotas.NewDefaultIncomingRateBurst(rateFnWithMetrics),
497 > quotas.NewDefaultIncomingRateBurst(rateFn),
498 > quotas.NewDefaultIncomingRateBurst(namespaceReplicationInducingRateFn),
499 > serviceConfig.OperatorRPSRatio,
500 > ),
501 > map[string]int{
502 > healthpb.Health_Check_FullMethodName: 0, // exclude health check requests from rate limiting.
503 > adminservice.AdminService_DeepHealthCheck_FullMethodName: 0, // exclude deep health check requests from rate limiting.
504 > },
505 > )
506 }
507
509 logger log.Logger,
510 dc *dynamicconfig.Collection,
511 > ) *interceptor.ContextMetadataInterceptor { fx.go
512 > setTrailer := dynamicconfig.FrontendContextMetadataSetTrailer.Get(dc)()
513 > return interceptor.NewContextMetadataInterceptor(setTrailer, logger)
514 > }
515
516 func MaskInternalErrorDetailsInterceptorProvider(
518 serviceConfig *Config,
519 namespaceRegistry namespace.Registry,
520 > ) *interceptor.MaskInternalErrorDetailsInterceptor { fx.go
521 > return interceptor.NewMaskInternalErrorDetailsInterceptor(
522 > serviceConfig.MaskInternalErrorDetails, namespaceRegistry, logger,
523 > )
524 > }
525
526 func NamespaceRateLimitInterceptorProvider(
531 metricsHandler metrics.Handler,
532 logger log.SnTaggedLogger,
533 > ) interceptor.NamespaceRateLimitInterceptor { fx.go
534 > var globalNamespaceRPS, globalNamespaceVisibilityRPS, globalNamespaceNamespaceReplicationInducingAPIsRPS dynamicconfig.IntPropertyFnWithNamespaceFilter
535 >
536 > switch serviceName {
537 > case primitives.FrontendService:
538 > globalNamespaceRPS = serviceConfig.GlobalNamespaceRPS
539 > globalNamespaceVisibilityRPS = serviceConfig.GlobalNamespaceVisibilityRPS
540 > globalNamespaceNamespaceReplicationInducingAPIsRPS = serviceConfig.GlobalNamespaceNamespaceReplicationInducingAPIsRPS
541 case primitives.InternalFrontendService:
542 globalNamespaceRPS = serviceConfig.InternalFEGlobalNamespaceRPS
548 }
549
550 > namespaceRateFn := calculator.NewLoggedNamespaceCalculator( fx.go
551 > calculator.ClusterAwareNamespaceQuotaCalculator{
552 > MemberCounter: frontendServiceResolver,
553 > PerInstanceQuota: serviceConfig.MaxNamespaceRPSPerInstance,
554 > GlobalQuota: globalNamespaceRPS,
555 > },
556 > log.With(logger, tag.ComponentRPCHandler, tag.ScopeNamespace),
557 > ).GetQuota
558 > visibilityRateFn := calculator.NewLoggedNamespaceCalculator(
559 > calculator.ClusterAwareNamespaceQuotaCalculator{
560 > MemberCounter: frontendServiceResolver,
561 > PerInstanceQuota: serviceConfig.MaxNamespaceVisibilityRPSPerInstance,
562 > GlobalQuota: globalNamespaceVisibilityRPS,
563 > },
564 > log.With(logger, tag.ComponentVisibilityHandler, tag.ScopeNamespace),
565 > ).GetQuota
566 > namespaceReplicationInducingRateFn := calculator.NewLoggedNamespaceCalculator(
567 > calculator.ClusterAwareNamespaceQuotaCalculator{
568 > MemberCounter: frontendServiceResolver,
569 > PerInstanceQuota: serviceConfig.MaxNamespaceNamespaceReplicationInducingAPIsRPSPerInstance,
570 > GlobalQuota: globalNamespaceNamespaceReplicationInducingAPIsRPS,
571 > },
572 > log.With(logger, tag.ComponentNamespaceReplication, tag.ScopeNamespace),
573 > ).GetQuota
574 > namespaceRateLimiter := quotas.NewNamespaceRequestRateLimiter(
575 > func(req quotas.Request) quotas.RequestRateLimiter {
576 return configs.NewRequestToRateLimiter(
577 quotas.NewNamespaceRateBurst(
594 },
595 )
596 > return interceptor.NewNamespaceRateLimitInterceptor( fx.go
597 > namespaceRegistry,
598 > namespaceRateLimiter,
599 > map[string]int{}, // no token overrides
600 > configs.PollTaskAPISet,
601 > serviceConfig.PollWaitForNamespaceRateLimitToken,
602 > metricsHandler,
603 > )
604 }
605
609 serviceResolver membership.ServiceResolver,
610 logger log.SnTaggedLogger,
611 > ) *interceptor.ConcurrentRequestLimitInterceptor { fx.go
612 > return interceptor.NewConcurrentRequestLimitInterceptor(
613 > namespaceRegistry,
614 > serviceResolver,
615 > logger,
616 > serviceConfig.MaxConcurrentLongRunningRequestsPerInstance,
617 > serviceConfig.MaxGlobalConcurrentLongRunningRequests,
618 > configs.ExecutionAPICountLimitOverride,
619 > )
620 > }
621
622 type NamespaceValidatorInterceptorParams struct {
629 func NamespaceValidatorInterceptorProvider(
630 params NamespaceValidatorInterceptorParams,
631 > ) *interceptor.NamespaceValidatorInterceptor { fx.go
632 > return interceptor.NewNamespaceValidatorInterceptor(
633 > params.NamespaceRegistry,
634 > params.ServiceConfig.EnableTokenNamespaceEnforcement,
635 > params.ServiceConfig.MaxIDLengthLimit,
636 > params.AdditionalAllowedMethodsDuringHandover,
637 > )
638 > }
639
640 > func SDKVersionInterceptorProvider() *interceptor.SDKVersionInterceptor { fx.go
641 > return interceptor.NewSDKVersionInterceptor()
642 > }
643
644 func CallerInfoInterceptorProvider(
645 namespaceRegistry namespace.Registry,
646 > ) *interceptor.CallerInfoInterceptor { fx.go
647 > return interceptor.NewCallerInfoInterceptor(namespaceRegistry)
648 > }
649
650 func SlowRequestLoggerInterceptorProvider(
651 logger log.Logger,
652 dc *dynamicconfig.Collection,
653 > ) *interceptor.SlowRequestLoggerInterceptor { fx.go
654 > return interceptor.NewSlowRequestLoggerInterceptor(
655 > logger,
656 > dynamicconfig.SlowRequestLoggingThreshold.Get(dc),
657 > )
658 > }
659
660 func PersistenceRateLimitingParamsProvider(
662 persistenceLazyLoadedServiceResolver service.PersistenceLazyLoadedServiceResolver,
663 logger log.SnTaggedLogger,
664 > ) service.PersistenceRateLimitingParams { fx.go
665 > return service.NewPersistenceRateLimitingParams(
666 > serviceConfig.PersistenceMaxQPS,
667 > serviceConfig.PersistenceGlobalMaxQPS,
668 > serviceConfig.PersistenceNamespaceMaxQPS,
669 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
670 > serviceConfig.PersistencePerShardNamespaceMaxQPS,
671 > serviceConfig.OperatorRPSRatio,
672 > serviceConfig.PersistenceQPSBurstRatio,
673 > serviceConfig.PersistenceDynamicRateLimitingParams,
674 > persistenceLazyLoadedServiceResolver,
675 > logger,
676 > )
677 > }
678
679 func VisibilityManagerProvider(
689 chasmRegistry *chasm.Registry,
690 serializer serialization.Serializer,
691 > ) (manager.VisibilityManager, error) { fx.go
692 > return visibility.NewManager(
693 > *persistenceConfig,
694 > persistenceServiceResolver,
695 > customVisibilityStoreFactory,
696 > nil, // frontend visibility never write
697 > saProvider,
698 > searchAttributesMapperProvider,
699 > namespaceRegistry,
700 > chasmRegistry,
701 > serviceConfig.VisibilityPersistenceMaxReadQPS,
702 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
703 > serviceConfig.OperatorRPSRatio,
704 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
705 > serviceConfig.EnableReadFromSecondaryVisibility,
706 > serviceConfig.VisibilityEnableShadowReadMode,
707 > dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff), // frontend visibility never write
708 > serviceConfig.VisibilityDisableOrderByClause,
709 > serviceConfig.VisibilityEnableManualPagination,
710 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
711 > metricsHandler,
712 > logger,
713 > serializer,
714 > )
715 > }
716
717 func FEReplicatorNamespaceReplicationQueueProvider(
718 namespaceReplicationQueue persistence.NamespaceReplicationQueue,
719 clusterMetadata cluster.Metadata,
720 > ) FEReplicatorNamespaceReplicationQueue { fx.go
721 > var replicatorNamespaceReplicationQueue persistence.NamespaceReplicationQueue
722 > if clusterMetadata.IsGlobalNamespaceEnabled() {
723 replicatorNamespaceReplicationQueue = namespaceReplicationQueue
724 }
725 > return replicatorNamespaceReplicationQueue fx.go
726 }
727
729 membershipMonitor membership.Monitor,
730 serviceName primitives.ServiceName,
731 > ) (membership.ServiceResolver, error) { fx.go
732 > return membershipMonitor.GetResolver(serviceName)
733 > }
734
735 func AdminHandlerProvider(
766 schedulerClient schedulerpb.SchedulerServiceClient,
767 namespaceDLQHandler nsreplication.DLQMessageHandler,
768 > ) *AdminHandler { fx.go
769 > args := NewAdminHandlerArgs{
770 > persistenceConfig,
771 > configuration,
772 > namespaceReplicationQueue,
773 > replicatorNamespaceReplicationQueue,
774 > visibilityMgr,
775 > logger,
776 > taskManager,
777 > fairTaskManager,
778 > persistenceExecutionManager,
779 > clusterMetadataManager,
780 > persistenceMetadataManager,
781 > clientFactory,
782 > clientBean,
783 > historyClient,
784 > sdkClientFactory,
785 > membershipMonitor,
786 > hostInfoProvider,
787 > metricsHandler,
788 > namespaceRegistry,
789 > saProvider,
790 > saManager,
791 > saMapperProvider,
792 > clusterMetadata,
793 > healthServer,
794 > eventSerializer,
795 > timeSource,
796 > chasmRegistry,
797 > namespaceDataMerger,
798 > schedulerClient,
799 > taskCategoryRegistry,
800 > matchingClient,
801 > }
802 > return NewAdminHandler(args, namespaceDLQHandler)
803 > }
804
805 // NamespaceDLQHandlerProvider provides the default namespace DLQ message handler.
812 logger log.SnTaggedLogger,
813 testHooks testhooks.TestHooks,
814 > ) nsreplication.DLQMessageHandler { fx.go
815 > taskExecutor := nsreplication.NewTaskExecutor(
816 > clusterMetadata.GetCurrentClusterName(),
817 > persistenceMetadataManager,
818 > namespaceDataMerger,
819 > namespaceAdmitter,
820 > logger,
821 > testHooks,
822 > )
823 > return nsreplication.NewDLQMessageHandler(
824 > taskExecutor,
825 > namespaceReplicationQueue,
826 > logger,
827 > )
828 > }
829
830 func OperatorHandlerProvider(
842 namespaceRegistry namespace.Registry,
843 nexusEndpointClient *NexusEndpointClient,
844 > ) *OperatorHandlerImpl { fx.go
845 > args := NewOperatorHandlerImplArgs{
846 > configuration,
847 > logger,
848 > sdkClientFactory,
849 > metricsHandler,
850 > visibilityMgr,
851 > saManager,
852 > healthServer,
853 > historyClient,
854 > clusterMetadataManager,
855 > clusterMetadata,
856 > clientFactory,
857 > namespaceRegistry,
858 > nexusEndpointClient,
859 > }
860 > return NewOperatorHandlerImpl(args)
861 > }
862
863 // callbackValidatorProvider creates a callback Validator using the production dynamic config keys
864 // so that existing operator configurations (callback.allowedAddresses) are honored.
865 > func callbackValidatorProvider(dc *dynamicconfig.Collection) callback.Validator { fx.go
866 > return callback.NewValidator(
867 > callback.MaxPerExecution.Get(dc),
868 > dynamicconfig.FrontendCallbackURLMaxLength.Get(dc),
869 > dynamicconfig.FrontendCallbackHeaderMaxSize.Get(dc),
870 > callback.AllowedAddresses.Get(dc),
871 > )
872 > }
873
874 func HandlerProvider(
911 registry *chasm.Registry,
912 frontendServiceResolver membership.ServiceResolver,
913 > ) Handler { fx.go
914 > workerDeploymentReadRateLimiter := configs.NewGlobalNamespaceRateLimiter(
915 > frontendServiceResolver,
916 > serviceConfig.GlobalWorkerDeploymentReadRPS,
917 > serviceConfig.GlobalWorkerDeploymentReadBurstRatio,
918 > log.With(logger, tag.ComponentRPCHandler, tag.ScopeNamespace),
919 > )
920 >
921 > wfHandler := NewWorkflowHandler(
922 > callbackValidator,
923 > serviceConfig,
924 > namespaceReplicationQueue,
925 > visibilityMgr,
926 > logger,
927 > throttledLogger,
928 > persistenceExecutionManager.GetName(),
929 > clusterMetadataManager,
930 > persistenceMetadataManager,
931 > historyClient,
932 > matchingClient,
933 > workerDeploymentStoreClient,
934 > schedulerClient,
935 > archiverProvider,
936 > payloadSerializer,
937 > namespaceRegistry,
938 > saMapperProvider,
939 > saProvider,
940 > saValidator,
941 > clusterMetadata,
942 > archivalMetadata,
943 > healthServer,
944 > timeSource,
945 > membershipMonitor,
946 > healthInterceptor,
947 > scheduleSpecBuilder,
948 > httpEnabled(cfg, serviceName),
949 > activityHandler,
950 > nexusOperationHandler,
951 > registry,
952 > workerDeploymentReadRateLimiter,
953 > chasmworkflow.NewValidator(
954 > chasmworkflow.NewConfig(dc),
955 > saMapperProvider,
956 > saValidator,
957 > ),
958 > )
959 > return wfHandler
960 > }
961
962 func RegisterNexusOperationHTTPHandler(
963 h *NexusOperationHTTPHandler,
964 router *mux.Router,
965 > ) { fx.go
966 > h.RegisterRoutes(router)
967 > }
968
969 func RegisterNexusCompletionHTTPHandler(
970 h *nexusCompletionHTTPHandler,
971 router *mux.Router,
972 > ) { fx.go
973 > h.RegisterRoutes(router)
974 > }
975
976 func RegisterOpenAPIHTTPHandler(
978 logger log.Logger,
979 router *mux.Router,
980 > ) *OpenAPIHTTPHandler { fx.go
981 > h := NewOpenAPIHTTPHandler(
982 > rateLimitInterceptor,
983 > logger,
984 > )
985 > h.RegisterRoutes(router)
986 > return h
987 > }
988
989 > func MuxRouterProvider() *mux.Router { fx.go
990 > // Instantiate a router to support additional route prefixes.
991 > return mux.NewRouter().UseEncodedPath()
992 > }
993
994 > func httpEnabled(cfg *config.Config, serviceName primitives.ServiceName) bool { fx.go
995 > // If the service is not the frontend service, HTTP API is disabled
996 > if serviceName != primitives.FrontendService && serviceName != primitives.InternalFrontendService {
997 return false
998 }
999 // If HTTP API port is 0, it is disabled
1000 > return cfg.Services[string(serviceName)].RPC.HTTPPort != 0 fx.go
1001 }
1002
1016 logger log.Logger,
1017 router *mux.Router,
1018 > ) (*HTTPAPIServer, error) { fx.go
1019 > if !httpEnabled(cfg, serviceName) {
1020 > return nil, nil fx.go
1021 > }
1022 rpcConfig := cfg.Services[string(serviceName)].RPC
1023 return NewHTTPAPIServer(
1042 nexusEndpointManager persistence.NexusEndpointManager,
1043 logger log.Logger,
1044 > ) *NexusEndpointClient { fx.go
1045 > clientConfig := newNexusEndpointClientConfig(dc)
1046 > return newNexusEndpointClient(
1047 > clientConfig,
1048 > namespaceRegistry,
1049 > matchingClient,
1050 > nexusEndpointManager,
1051 > logger,
1052 > )
1053 > }
1054
1055 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
1056 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
1057 > }
go.temporal.io/server/temporal/fx.go 472 covered LOC · 92 ranges

Open complete file

158 )
159
160 > func NewServerFx(topLevelModule fx.Option, opts ...ServerOption) (*ServerFx, error) { fx.go
161 > var s ServerFx
162 > s.app = fx.New(
163 > topLevelModule,
164 > fx.Supply(opts),
165 > fx.Populate(&s.startupSynchronizationMode),
166 > fx.Populate(&s.logger),
167 > )
168 > if err := s.app.Err(); err != nil {
169 return nil, err
170 }
171 > return &s, nil fx.go
172 }
173
174 > func ServerOptionsProvider(opts []ServerOption) (serverOptionsProvider, error) { fx.go
175 > so := newServerOptions(opts)
176 >
177 > err := so.loadAndValidate()
178 > if err != nil {
179 return serverOptionsProvider{}, err
180 }
181
182 // Logger
183 > logger := so.logger fx.go
184 > if logger == nil {
185 logger = log.NewZapLogger(log.BuildZapLogger(so.config.Log))
186 }
187
188 > persistenceConfig := so.config.Persistence fx.go
189 > err = verifyPersistenceCompatibleVersion(persistenceConfig, so.persistenceServiceResolver, logger)
190 > if err != nil {
191 return serverOptionsProvider{}, err
192 }
193
194 > stopChan := make(chan any) fx.go
195 >
196 > // ClientFactoryProvider
197 > clientFactoryProvider := so.clientFactoryProvider
198 > if clientFactoryProvider == nil {
199 > clientFactoryProvider = client.NewFactoryProvider()
200 > }
201
202 // MetricsHandler
203 > metricHandler := so.metricHandler fx.go
204 > if metricHandler == nil {
205 > metricHandler, err = metrics.MetricsHandlerFromConfig(logger, so.config.Global.Metrics)
206 > if err != nil {
207 return serverOptionsProvider{}, fmt.Errorf("unable to create metrics handler: %w", err)
208 }
212 // if injected, else a no-op provider that discards events. A deployment opts in by injecting a
213 // provider via WithCustomEventLoggerProvider.
214 > eventLoggerProvider := so.eventLoggerProvider fx.go
215 > if eventLoggerProvider == nil {
216 > eventLoggerProvider = lognoop.NewLoggerProvider()
217 > }
218
219 // DynamicConfigClient
220 > dcClient := so.dynamicConfigClient fx.go
221 > if dcClient == nil {
222 dcConfig := so.config.DynamicConfigClient
223 if dcConfig != nil {
234
235 // TLSConfigProvider
236 > tlsConfigProvider := so.tlsConfigProvider fx.go
237 > if tlsConfigProvider == nil {
238 > tlsConfigProvider, err = encryption.NewTLSConfigProviderFromConfig(so.config.Global.TLS, metricHandler, logger, nil)
239 > if err != nil {
240 return serverOptionsProvider{}, err
241 }
243
244 // EsConfig / EsClient
245 > var esConfig *esclient.Config fx.go
246 > var esClient esclient.Client
247 >
248 > if persistenceConfig.SecondaryVisibilityConfigExist() &&
249 > persistenceConfig.DataStores[persistenceConfig.SecondaryVisibilityStore].Elasticsearch != nil {
250 esConfig = persistenceConfig.DataStores[persistenceConfig.SecondaryVisibilityStore].Elasticsearch
251 esConfig.SetHttpClient(so.elasticsearchHttpClient)
252 }
253 > if persistenceConfig.VisibilityConfigExist() && fx.go
254 > persistenceConfig.DataStores[persistenceConfig.VisibilityStore].Elasticsearch != nil {
255 esConfig = persistenceConfig.DataStores[persistenceConfig.VisibilityStore].Elasticsearch
256 esConfig.SetHttpClient(so.elasticsearchHttpClient)
257 }
258
259 > if esConfig != nil { fx.go
260 esHttpClient := so.elasticsearchHttpClient
261 if esHttpClient == nil {
275
276 // check that when static hosts are defined, they are defined for all required hosts
277 > if len(so.hostsByService) > 0 { fx.go
278 for _, service := range DefaultServices {
279 hosts := so.hostsByService[primitives.ServiceName(service)]
284 }
285
286 > if so.config.Global.Authorization.RemoteClusterAuth.Require && so.tokenProvider == nil { fx.go
287 return serverOptionsProvider{}, errors.New("global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider")
288 }
291 // Coarse check: any remote-cluster TLS entry passes; per-hostname config is still validated
292 // lazily on first dial.
293 > if so.tokenProvider != nil && so.tlsConfigProvider == nil && len(so.config.Global.TLS.RemoteClusters) == 0 { fx.go
294 return serverOptionsProvider{}, errors.New("WithTokenProvider is set but no remote-cluster TLS is configured: supply global.tls.remoteClusters in config, or pass a provider via WithTLSConfigProvider")
295 }
296
297 > return serverOptionsProvider{ fx.go
298 > ServerOptions: so,
299 > StopChan: stopChan,
300 > StartupSynchronizationMode: so.startupSynchronizationMode,
301 >
302 > Config: so.config,
303 > PProfConfig: &so.config.Global.PProf,
304 > LogConfig: so.config.Log,
305 >
306 > ServiceNames: so.serviceNames,
307 > ServiceHosts: so.hostsByService,
308 > NamespaceLogger: so.namespaceLogger,
309 >
310 > ServiceResolver: so.persistenceServiceResolver,
311 > CustomDataStoreFactory: so.customDataStoreFactory,
312 > CustomVisibilityStore: so.customVisibilityStoreFactory,
313 > CustomHistoryArchiverFactory: so.customHistoryArchiverFactory,
314 > CustomVisibilityArchiverFactory: so.customVisibilityArchiverFactory,
315 >
316 > SearchAttributesMapper: so.searchAttributesMapper,
317 > CustomFrontendInterceptors: so.customFrontendInterceptors,
318 > Authorizer: so.authorizer,
319 > ClaimMapper: so.claimMapper,
320 > AudienceGetter: so.audienceGetter,
321 > TokenProvider: so.tokenProvider,
322 >
323 > Logger: logger,
324 > ClientFactoryProvider: clientFactoryProvider,
325 > DynamicConfigClient: dcClient,
326 > TLSConfigProvider: tlsConfigProvider,
327 > EsClient: esClient,
328 > MetricsHandler: metricHandler,
329 > EventLoggerProvider: eventLoggerProvider,
330 > }, nil
331 }
332
333 // Start temporal server.
334 // This function should be called only once, Server doesn't support multiple restarts.
335 > func (s *ServerFx) Start() error { fx.go
336 > err := s.app.Start(context.Background())
337 > if err != nil {
338 return err
339 }
340
341 > if s.startupSynchronizationMode.blockingStart { fx.go
342 // If s.so.interruptCh is nil this will wait forever.
343 interruptSignal := <-s.startupSynchronizationMode.interruptCh
346 }
347
348 > return nil fx.go
349 }
350
351 // Stop stops the server.
352 > func (s *ServerFx) Stop() error { fx.go
353 > return s.app.Stop(context.Background())
354 > }
355
356 > func (svc *ServicesMetadata) Stop(ctx context.Context) { fx.go
357 > stopCtx, cancelFunc := context.WithTimeout(ctx, serviceStopTimeout)
358 > defer cancelFunc()
359 > err := svc.app.Stop(stopCtx)
360 > if err != nil {
361 svc.logger.Error("Failed to stop service", tag.Service(svc.serviceName), tag.Error(err))
362 }
405 // into fx providers here. Essentially, we want an `fx.In` object in the server graph, and an `fx.Out` object in the
406 // service graphs. This is a workaround to achieve something similar.
407 > func (params ServiceProviderParamsCommon) GetCommonServiceOptions(serviceName primitives.ServiceName) fx.Option { fx.go
408 > membershipModule := ringpop.MembershipModule
409 > if len(params.StaticServiceHosts) > 0 {
410 membershipModule = static.MembershipModule(params.StaticServiceHosts)
411 }
412
413 > return fx.Options( fx.go
414 > fx.Supply(
415 > serviceName,
416 > params.PersistenceConfig,
417 > params.ClusterMetadata,
418 > params.Cfg,
419 > params.SpanExporters,
420 > ),
421 > fx.Provide(
422 > resource.DefaultSnTaggedLoggerProvider,
423 > params.PersistenceFactoryProvider,
424 > func() persistenceClient.AbstractDataStoreFactory {
425 > return params.DataStoreFactory
426 > },
427 > func() visibility.VisibilityStoreFactory {
428 > return params.VisibilityStoreFactory
429 > },
430 > func() provider.CustomHistoryArchiverFactory {
431 > return params.CustomHistoryArchiverFactory
432 > },
433 > func() provider.CustomVisibilityArchiverFactory {
434 > return params.CustomVisibilityArchiverFactory
435 > },
436 > func() client.FactoryProvider {
437 > return params.ClientFactoryProvider
438 > },
439 > func() authorization.JWTAudienceMapper {
440 > return params.AudienceGetter
441 > },
442 > func() resolver.ServiceResolver {
443 > return params.PersistenceServiceResolver
444 > },
445 > func() searchattribute.Mapper {
446 > return params.SearchAttributesMapper
447 > },
448 > func() authorization.Authorizer {
449 > return params.Authorizer
450 > },
451 func() authorization.ClaimMapper {
452 return params.ClaimMapper
453 },
454 > func() auth.TokenProvider { fx.go
455 > return params.TokenProvider
456 > },
457 > func() encryption.TLSConfigProvider {
458 > return params.TlsConfigProvider
459 > },
460 > func() dynamicconfig.Client {
461 > return params.DynamicConfigClient
462 > },
463 > func() log.Logger {
464 > return params.Logger
465 > },
466 > func() metrics.Handler {
467 > return params.MetricsHandler.WithTags(metrics.ServiceNameTag(serviceName))
468 > },
469 > func() otellog.Logger {
470 > return wideevents.NewLogger(params.EventLoggerProvider, string(serviceName))
471 > },
472 func() esclient.Client {
473 return params.EsClient
474 },
475 > func() resource.NamespaceLogger { fx.go
476 > return params.NamespaceLogger
477 > },
478 > func() tasks.TaskCategoryRegistry {
479 > return params.TaskCategoryRegistry
480 > },
481 ),
482 ServiceTracingModule,
494 // registry in the server graph, and then propagate it to the service graphs. Otherwise, it would be isolated to the
495 // history service's graph.
496 > func TaskCategoryRegistryProvider(archivalMetadata archiver.ArchivalMetadata) tasks.TaskCategoryRegistry { fx.go
497 > registry := tasks.NewDefaultTaskCategoryRegistry()
498 > if archivalMetadata.GetHistoryConfig().StaticClusterState() == archiver.ArchivalEnabled ||
499 > archivalMetadata.GetVisibilityConfig().StaticClusterState() == archiver.ArchivalEnabled {
500 registry.AddCategory(tasks.CategoryArchival)
501 }
502 > return registry fx.go
503 }
504
505 > func NewService(app *fx.App, serviceName primitives.ServiceName, logger log.Logger) ServicesGroupOut { fx.go
506 > return ServicesGroupOut{
507 > Services: &ServicesMetadata{
508 > app: app,
509 > serviceName: serviceName,
510 > logger: logger,
511 > },
512 > }
513 > }
514
515 func HistoryServiceProvider(
516 params ServiceProviderParamsCommon,
517 > ) (ServicesGroupOut, error) { fx.go
518 > serviceName := primitives.HistoryService
519 >
520 > if _, ok := params.ServiceNames[serviceName]; !ok {
521 params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
522 return ServicesGroupOut{}, nil
523 }
524
525 > app := fx.New( fx.go
526 > params.GetCommonServiceOptions(serviceName),
527 > history.QueueModule,
528 > history.Module,
529 > replication.Module,
530 > )
531 >
532 > return NewService(app, serviceName, params.Logger), app.Err()
533 }
534
535 func MatchingServiceProvider(
536 params ServiceProviderParamsCommon,
537 > ) (ServicesGroupOut, error) { fx.go
538 > serviceName := primitives.MatchingService
539 >
540 > if _, ok := params.ServiceNames[serviceName]; !ok {
541 params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
542 return ServicesGroupOut{}, nil
543 }
544
545 > app := fx.New( fx.go
546 > params.GetCommonServiceOptions(serviceName),
547 > matching.Module,
548 > )
549 >
550 > return NewService(app, serviceName, params.Logger), app.Err()
551 }
552
553 func FrontendServiceProvider(
554 params ServiceProviderParamsCommon,
555 > ) (ServicesGroupOut, error) { fx.go
556 > return genericFrontendServiceProvider(params, primitives.FrontendService)
557 > }
558
559 func InternalFrontendServiceProvider(
560 params ServiceProviderParamsCommon,
561 > ) (ServicesGroupOut, error) { fx.go
562 > return genericFrontendServiceProvider(params, primitives.InternalFrontendService)
563 > }
564
565 func genericFrontendServiceProvider(
566 params ServiceProviderParamsCommon,
567 serviceName primitives.ServiceName,
568 > ) (ServicesGroupOut, error) { fx.go
569 > if _, ok := params.ServiceNames[serviceName]; !ok {
570 > params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
571 > return ServicesGroupOut{}, nil
572 > }
573
574 > app := fx.New( fx.go
575 > params.GetCommonServiceOptions(serviceName),
576 > fx.Supply(params.CustomFrontendInterceptors),
577 > fx.Supply([]grpc.StreamServerInterceptor{}),
578 > fx.Decorate(func() authorization.ClaimMapper {
579 > switch serviceName {
580 > case primitives.FrontendService:
581 > return params.ClaimMapper
582 case primitives.InternalFrontendService:
583 return authorization.NewInternalClaimMapper()
586 }
587 }),
588 > fx.Decorate(func() log.SnTaggedLogger { fx.go
589 > // Use "frontend" for logs even if serviceName is "internal-frontend", but add an
590 > // extra tag to differentiate.
591 > tags := []tag.Tag{tag.Service(primitives.FrontendService)}
592 > if serviceName == primitives.InternalFrontendService {
593 tags = append(tags, tag.Bool("internal-frontend", true))
594 }
595 > return log.With(params.Logger, tags...) fx.go
596 }),
597 frontend.Module,
598 )
599
600 > return NewService(app, serviceName, params.Logger), app.Err() fx.go
601 }
602
603 func WorkerServiceProvider(
604 params ServiceProviderParamsCommon,
605 > ) (ServicesGroupOut, error) { fx.go
606 > serviceName := primitives.WorkerService
607 >
608 > if _, ok := params.ServiceNames[serviceName]; !ok {
609 params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
610 return ServicesGroupOut{}, nil
611 }
612
613 > app := fx.New( fx.go
614 > params.GetCommonServiceOptions(serviceName),
615 > worker.Module,
616 > )
617 >
618 > return NewService(app, serviceName, params.Logger), app.Err()
619 }
620
632 metricsHandler metrics.Handler,
633 serializer serialization.Serializer,
634 > ) (*cluster.Config, config.Persistence, error) { fx.go
635 > ctx := context.TODO()
636 > logger = log.With(logger, tag.ComponentMetadataInitializer)
637 > metricsHandler = metricsHandler.WithTags(metrics.ServiceNameTag(primitives.ServerService))
638 > clusterName := persistenceClient.ClusterName(svc.ClusterMetadata.CurrentClusterName)
639 > dataStoreFactory := persistenceClient.DataStoreFactoryProvider(
640 > clusterName,
641 > persistenceServiceResolver,
642 > &svc.Persistence,
643 > customDataStoreFactory,
644 > logger,
645 > metricsHandler,
646 > telemetry.NoopTracerProvider,
647 > serializer,
648 > )
649 > factory := persistenceFactoryProvider(persistenceClient.NewFactoryParams{
650 > DataStoreFactory: dataStoreFactory,
651 > Cfg: &svc.Persistence,
652 > PersistenceMaxQPS: nil,
653 > PersistenceNamespaceMaxQPS: nil,
654 > ClusterName: persistenceClient.ClusterName(svc.ClusterMetadata.CurrentClusterName),
655 > MetricsHandler: metricsHandler,
656 > Logger: logger,
657 > Serializer: serializer,
658 > })
659 > defer factory.Close()
660 >
661 > clusterMetadataManager, err := factory.NewClusterMetadataManager()
662 > if err != nil {
663 return svc.ClusterMetadata, svc.Persistence, fmt.Errorf("error initializing cluster metadata manager: %w", err)
664 }
665 > defer clusterMetadataManager.Close() fx.go
666 >
667 > visCSAOverride := map[enumspb.IndexedValueType]int{}
668 > for tpName, value := range svc.Visibility.PersistenceCustomSearchAttributes {
669 saType, ok := enumspb.IndexedValueType_shorthandValue[tpName]
670 if !ok {
684 }
685
686 > visDataStores := []config.DataStore{ fx.go
687 > svc.Persistence.GetVisibilityStoreConfig(),
688 > svc.Persistence.GetSecondaryVisibilityStoreConfig(),
689 > }
690 > indexSearchAttributes := make(map[string]*persistencespb.IndexSearchAttributes)
691 > for _, ds := range visDataStores {
692 > indexSearchAttributes[ds.GetIndexName()] = sadefs.GetDBIndexSearchAttributes(visCSAOverride)
693 > }
694
695 > clusterMetadata := svc.ClusterMetadata fx.go
696 > if len(clusterMetadata.ClusterInformation) > 1 {
697 logger.Warn(
698 "All remote cluster settings under ClusterMetadata.ClusterInformation config will be ignored. "+
700 tag.Key("clusterInformation"))
701 }
702 > if _, ok := clusterMetadata.ClusterInformation[clusterMetadata.CurrentClusterName]; !ok { fx.go
703 logger.Error("Current cluster setting is missing under clusterMetadata.ClusterInformation",
704 tag.ClusterName(clusterMetadata.CurrentClusterName))
705 return svc.ClusterMetadata, svc.Persistence, missingCurrentClusterMetadataErr
706 }
707 > ctx = headers.SetCallerInfo(ctx, headers.SystemOperatorCallerInfo) fx.go
708 > resp, err := clusterMetadataManager.GetClusterMetadata(
709 > ctx,
710 > &persistence.GetClusterMetadataRequest{ClusterName: clusterMetadata.CurrentClusterName},
711 > )
712 > switch err.(type) {
713 case nil:
714 // Update current record
728 logger,
729 )
730 > case *serviceerror.NotFound: fx.go
731 > // Initialize current cluster record
732 > if initErr := initCurrentClusterMetadataRecord(
733 > ctx,
734 > clusterMetadataManager,
735 > svc,
736 > indexSearchAttributes,
737 > logger,
738 > ); initErr != nil {
739 return svc.ClusterMetadata, svc.Persistence, initErr
740 }
743 }
744
745 > clusterLoader := NewClusterMetadataLoader(clusterMetadataManager, logger) fx.go
746 > err = clusterLoader.LoadAndMergeWithStaticConfig(ctx, svc)
747 > if err != nil {
748 return svc.ClusterMetadata, svc.Persistence, fmt.Errorf("error while loading metadata from cluster: %w", err)
749 }
750 > return svc.ClusterMetadata, svc.Persistence, nil fx.go
751 }
752
757 initialIndexSearchAttributes map[string]*persistencespb.IndexSearchAttributes,
758 logger log.Logger,
759 > ) error { fx.go
760 > var clusterId string
761 > currentClusterName := svc.ClusterMetadata.CurrentClusterName
762 > currentClusterInfo := svc.ClusterMetadata.ClusterInformation[currentClusterName]
763 > if uuid.Validate(currentClusterInfo.ClusterID) != nil {
764 > if currentClusterInfo.ClusterID != "" {
765 logger.Warn("Cluster Id in Cluster Metadata config is not a valid uuid. Generating a new Cluster Id")
766 }
767 > clusterId = uuid.NewString() fx.go
768 } else {
769 clusterId = currentClusterInfo.ClusterID
770 }
771
772 > applied, err := clusterMetadataManager.SaveClusterMetadata( fx.go
773 > ctx,
774 > &persistence.SaveClusterMetadataRequest{
775 > ClusterMetadata: &persistencespb.ClusterMetadata{
776 > HistoryShardCount: svc.Persistence.NumHistoryShards,
777 > ClusterName: currentClusterName,
778 > ClusterId: clusterId,
779 > ClusterAddress: currentClusterInfo.RPCAddress,
780 > HttpAddress: currentClusterInfo.HTTPAddress,
781 > FailoverVersionIncrement: svc.ClusterMetadata.FailoverVersionIncrement,
782 > InitialFailoverVersion: currentClusterInfo.InitialFailoverVersion,
783 > IsGlobalNamespaceEnabled: svc.ClusterMetadata.EnableGlobalNamespace,
784 > IsConnectionEnabled: currentClusterInfo.Enabled,
785 > UseClusterIdMembership: true, // Enable this for new cluster after 1.19. This is to prevent two clusters join into one ring.
786 > IndexSearchAttributes: initialIndexSearchAttributes,
787 > Tags: svc.ClusterMetadata.Tags,
788 > },
789 > })
790 > if err != nil {
791 logger.Warn("Failed to save cluster metadata.", tag.Error(err), tag.ClusterName(currentClusterName))
792 return err
793 }
794 > if !applied { fx.go
795 logger.Error("Failed to apply cluster metadata.", tag.ClusterName(currentClusterName))
796 return clusterMetadataInitErr
797 }
798 > return nil fx.go
799 }
800
916 }
917
918 > func PersistenceFactoryProvider() persistenceClient.FactoryProviderFn { fx.go
919 > return persistenceClient.FactoryProvider
920 > }
921
922 func ServerLifetimeHooks(
923 lc fx.Lifecycle,
924 svr *ServerImpl,
925 > ) { fx.go
926 > lc.Append(fx.StartStopHook(svr.Start, svr.Stop))
927 > }
928
929 func verifyPersistenceCompatibleVersion(
931 persistenceServiceResolver resolver.ServiceResolver,
932 logger log.Logger,
933 > ) error { fx.go
934 > // cassandra schema version validation
935 > if err := cassandra.VerifyCompatibleVersion(cfg, persistenceServiceResolver, logger); err != nil {
936 return fmt.Errorf("cassandra schema version compatibility check failed: %w", err)
937 }
938 // sql schema version validation
939 > if err := sql.VerifyCompatibleVersion(cfg, persistenceServiceResolver, logger); err != nil { fx.go
940 return fmt.Errorf("sql schema version compatibility check failed: %w", err)
941 }
942 > return nil fx.go
943 }
944
956 // - []go.opentelemetry.io/otel/sdk/trace.SpanExporter
957 var TraceExportModule = fx.Options(
958 > fx.Provide(func(inputs SpanExporterInputs) ([]otelsdktrace.SpanExporter, error) { fx.go
959 > var tracingReady atomic.Bool
960 > otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
961 if tracingReady.Load() { // ignore errors during startup
962 inputs.Logger.Warn("OTEL error", tag.Error(err), tag.ServiceErrorType(err))
965
966 // (1) Exporters from config.
967 > exportersByType := map[telemetry.SpanExporterType]otelsdktrace.SpanExporter{} fx.go
968 > if inputs.Config != nil {
969 > var err error
970 > exportersByType, err = inputs.Config.ExporterConfig.SpanExporters()
971 > if err != nil {
972 return nil, err
973 }
975
976 // (2) Exporters from env variables.
977 > exportersByTypeFromEnv, err := telemetry.SpanExportersFromEnv(os.LookupEnv) fx.go
978 > if err != nil {
979 return nil, err
980 }
981
982 // (3) Exporters from code (ie from testing).
983 > customExportersByType := inputs.Config.ExporterConfig.CustomExporters fx.go
984 >
985 > // Merge exporters.
986 > maps.Copy(exportersByType, exportersByTypeFromEnv) // env overrides config
987 > maps.Copy(exportersByType, customExportersByType) // custom overrides all
988 > exporters := expmaps.Values(exportersByType)
989 >
990 > // Configure exporters' lifecycle hooks.
991 > inputs.Lifecycyle.Append(fx.Hook{
992 > OnStart: func(ctx context.Context) error {
993 > err = startAll(exporters)(ctx)
994 > tracingReady.Store(true)
995 > return err
996 > },
997 OnStop: shutdownAll(exporters),
998 })
999 > return exporters, nil fx.go
1000 }),
1001 )
1020 fx.Provide(
1021 fx.Annotate(
1022 > func(exps []otelsdktrace.SpanExporter, opts []otelsdktrace.BatchSpanProcessorOption) []otelsdktrace.SpanProcessor { fx.go
1023 > sps := make([]otelsdktrace.SpanProcessor, 0, len(exps))
1024 > for _, exp := range exps {
1025 sps = append(sps, otelsdktrace.NewBatchSpanProcessor(exp, opts...))
1026 }
1027 > return sps fx.go
1028 },
1029 fx.ParamTags(`optional:"true"`, ``),
1032 fx.Provide(
1033 fx.Annotate(
1034 > func(rsn primitives.ServiceName, rsi resource.InstanceID) (*otelresource.Resource, error) { fx.go
1035 > attrs := []attribute.KeyValue{
1036 > semconv.ServiceNameKey.String(telemetry.ResourceServiceName(rsn, os.LookupEnv)),
1037 > semconv.ServiceVersionKey.String(headers.ServerVersion),
1038 > }
1039 > if rsi != "" {
1040 attrs = append(attrs, semconv.ServiceInstanceIDKey.String(string(rsi)))
1041 }
1042
1043 > return otelresource.New(context.Background(), fx.go
1044 > otelresource.WithProcess(),
1045 > otelresource.WithOS(),
1046 > otelresource.WithHost(),
1047 > otelresource.WithContainer(),
1048 > otelresource.WithAttributes(attrs...),
1049 > )
1050 },
1051 fx.ParamTags(``, `optional:"true"`),
1052 ),
1053 ),
1054 > fx.Provide(func(lc fx.Lifecycle, r *otelresource.Resource, sps []otelsdktrace.SpanProcessor) trace.TracerProvider { fx.go
1055 > if len(sps) == 0 {
1056 > return telemetry.NoopTracerProvider fx.go
1057 > }
1058 opts := make([]otelsdktrace.TracerProviderOption, 0, len(sps)+1)
1059 opts = append(opts, otelsdktrace.WithResource(r))
1082 }),
1083 // Haven't had use for baggage propagation yet
1084 > fx.Provide(func() propagation.TextMapPropagator { return propagation.TraceContext{} }), fx.go
1085 fx.Provide(telemetry.NewServerStatsHandler),
1086 fx.Provide(telemetry.NewClientStatsHandler),
1088 )
1089
1090 > func startAll(exporters []otelsdktrace.SpanExporter) func(ctx context.Context) error { fx.go
1091 > type starter interface{ Start(context.Context) error }
1092 > return func(ctx context.Context) error {
1093 > for _, e := range exporters {
1094 if starter, ok := e.(starter); ok {
1095 err := starter.Start(ctx)
1099 }
1100 }
1101 > return nil fx.go
1102 }
1103 }
1104
1105 > func shutdownAll(exporters []otelsdktrace.SpanExporter) func(ctx context.Context) error { fx.go
1106 > return func(ctx context.Context) error {
1107 > shutdownCtx, cancel := context.WithTimeout(context.Background(), 1*time.Second) fx.go
1108 > defer cancel()
1109 >
1110 > for _, e := range exporters {
1111 err := e.Shutdown(shutdownCtx)
1112 if errors.Is(err, context.DeadlineExceeded) {
1116 }
1117 }
1118 > return nil fx.go
1119 }
1120 }
1121
1122 > var FxLogAdapter = fx.WithLogger(func(logger log.Logger) fxevent.Logger { fx.go
1123 > return &fxLogAdapter{logger: logger}
1124 > })
1125
1126 type fxLogAdapter struct {
1128 }
1129
1130 > func (l *fxLogAdapter) LogEvent(e fxevent.Event) { fx.go
1131 > switch e := e.(type) {
1132 > case *fxevent.OnStartExecuting:
1133 > l.logger.Debug("OnStart hook executing",
1134 > tag.ComponentFX,
1135 > tag.String("callee", e.FunctionName),
1136 > tag.String("caller", e.CallerName),
1137 > )
1138 > case *fxevent.OnStartExecuted:
1139 > if e.Err != nil {
1140 l.logger.Error("OnStart hook failed",
1141 tag.ComponentFX,
1144 tag.Error(e.Err),
1145 )
1146 > } else { fx.go
1147 > l.logger.Debug("OnStart hook executed",
1148 > tag.ComponentFX,
1149 > tag.String("callee", e.FunctionName),
1150 > tag.String("caller", e.CallerName),
1151 > tag.Stringer("runtime", e.Runtime),
1152 > )
1153 > }
1154 > case *fxevent.OnStopExecuting: fx.go
1155 > l.logger.Debug("OnStop hook executing",
1156 > tag.ComponentFX,
1157 > tag.String("callee", e.FunctionName),
1158 > tag.String("caller", e.CallerName),
1159 > )
1160 > case *fxevent.OnStopExecuted:
1161 > if e.Err != nil {
1162 l.logger.Error("OnStop hook failed",
1163 tag.ComponentFX,
1166 tag.Error(e.Err),
1167 )
1168 > } else { fx.go
1169 > l.logger.Debug("OnStop hook executed",
1170 > tag.ComponentFX,
1171 > tag.String("callee", e.FunctionName),
1172 > tag.String("caller", e.CallerName),
1173 > tag.Stringer("runtime", e.Runtime),
1174 > )
1175 > }
1176 > case *fxevent.Supplied: fx.go
1177 > if e.Err != nil {
1178 l.logger.Error("supplied",
1179 tag.ComponentFX,
1182 tag.Error(e.Err))
1183 }
1184 > case *fxevent.Provided: fx.go
1185 > if e.Err != nil {
1186 l.logger.Error("error encountered while applying options",
1187 tag.ComponentFX,
1196 tag.Error(e.Err))
1197 }
1198 > case *fxevent.Decorated: fx.go
1199 > if e.Err != nil {
1200 l.logger.Error("error encountered while applying options",
1201 tag.ComponentFX,
1203 tag.Error(e.Err))
1204 }
1205 > case *fxevent.Run: fx.go
1206 > if e.Err != nil {
1207 l.logger.Error("error returned",
1208 tag.ComponentFX,
1213 )
1214 }
1215 > case *fxevent.Invoking: fx.go
1216 > // Do not log stack as it will make logs hard to read.
1217 > l.logger.Debug("invoking",
1218 > tag.ComponentFX,
1219 > tag.String("function", e.FunctionName),
1220 > tag.String("module", e.ModuleName),
1221 > )
1222 > case *fxevent.Invoked:
1223 > if e.Err != nil {
1224 l.logger.Error("invoke failed",
1225 tag.ComponentFX,
1234 tag.ComponentFX,
1235 tag.Stringer("signal", e.Signal))
1236 > case *fxevent.Stopped: fx.go
1237 > if e.Err != nil {
1238 l.logger.Error("stop failed", tag.ComponentFX, tag.Error(e.Err))
1239 }
1244 l.logger.Error("rollback failed", tag.ComponentFX, tag.Error(e.Err))
1245 }
1246 > case *fxevent.Started: fx.go
1247 > if e.Err != nil {
1248 l.logger.Error("start failed", tag.ComponentFX, tag.Error(e.Err))
1249 > } else { fx.go
1250 > l.logger.Debug("started", tag.ComponentFX)
1251 > }
1252 > case *fxevent.LoggerInitialized:
1253 > if e.Err != nil {
1254 l.logger.Error("custom logger initialization failed", tag.ComponentFX, tag.Error(e.Err))
1255 > } else { fx.go
1256 > l.logger.Debug("initialized custom fxevent.Logger",
1257 > tag.ComponentFX,
1258 > tag.String("function", e.ConstructorName))
1259 > }
1260 > case *fxevent.BeforeRun:
1261 > l.logger.Debug("before run",
1262 > tag.ComponentFX,
1263 > tag.String("name", e.Name),
1264 > tag.String("kind", e.Kind),
1265 > tag.String("module", e.ModuleName),
1266 > )
1267 default:
1268 l.logger.Warn("unknown fx log type, update fxLogAdapter",
go.temporal.io/server/service/history/configs/config.go 392 covered LOC · 1 range

Open complete file

445 dc *dynamicconfig.Collection,
446 numberOfShards int32,
447 > ) *Config { config.go
448 > cfg := &Config{
449 > NumberOfShards: numberOfShards,
450 >
451 > EnableReplicationStream: dynamicconfig.EnableReplicationStream.Get(dc),
452 > EmitReplicationLifecycleEvents: dynamicconfig.EmitReplicationLifecycleEvents.Get(dc),
453 > EnableCloseInboundReplicationStreamOnShutdown: dynamicconfig.EnableCloseInboundReplicationStreamOnShutdown.Get(dc),
454 > EnableSeparateReplicationEnableFlag: dynamicconfig.EnableSeparateReplicationEnableFlag.Get(dc),
455 > HistoryReplicationDLQV2: dynamicconfig.EnableHistoryReplicationDLQV2.Get(dc),
456 >
457 > RPS: dynamicconfig.HistoryRPS.Get(dc),
458 > NamespaceRPS: dynamicconfig.HistoryNamespaceRPS.Get(dc),
459 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
460 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
461 > PersistenceMaxQPS: dynamicconfig.HistoryPersistenceMaxQPS.Get(dc),
462 > PersistenceGlobalMaxQPS: dynamicconfig.HistoryPersistenceGlobalMaxQPS.Get(dc),
463 > PersistenceNamespaceMaxQPS: dynamicconfig.HistoryPersistenceNamespaceMaxQPS.Get(dc),
464 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.HistoryPersistenceGlobalNamespaceMaxQPS.Get(dc),
465 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.HistoryPersistencePerShardNamespaceMaxQPS.Get(dc),
466 > PersistenceDynamicRateLimitingParams: dynamicconfig.HistoryPersistenceDynamicRateLimitingParams.Get(dc),
467 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
468 > AlignMembershipChange: dynamicconfig.HistoryAlignMembershipChange.Get(dc),
469 > ShutdownDrainDuration: dynamicconfig.HistoryShutdownDrainDuration.Get(dc),
470 > StartupMembershipJoinDelay: dynamicconfig.HistoryStartupMembershipJoinDelay.Get(dc),
471 > AllowResetWithPendingChildren: dynamicconfig.AllowResetWithPendingChildren.Get(dc),
472 > MaxAutoResetPoints: dynamicconfig.HistoryMaxAutoResetPoints.Get(dc),
473 > DefaultWorkflowTaskTimeout: dynamicconfig.DefaultWorkflowTaskTimeout.Get(dc),
474 >
475 > MaxLocalParentWorkflowVerificationDuration: dynamicconfig.MaxLocalParentWorkflowVerificationDuration.Get(dc),
476 >
477 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
478 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
479 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
480 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
481 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
482 > SecondaryVisibilityWritingMode: dynamicconfig.SecondaryVisibilityWritingMode.Get(dc),
483 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
484 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
485 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
486 > VisibilityAllowList: dynamicconfig.VisibilityAllowList.Get(dc),
487 > SuppressErrorSetSystemSearchAttribute: dynamicconfig.SuppressErrorSetSystemSearchAttribute.Get(dc),
488 >
489 > EmitShardLagLog: dynamicconfig.EmitShardLagLog.Get(dc),
490 > EnableDataLossMetrics: dynamicconfig.EnableDataLossMetrics.Get(dc),
491 > // HistoryCacheLimitSizeBased should not change during runtime.
492 > HistoryCacheLimitSizeBased: dynamicconfig.HistoryCacheSizeBasedLimit.Get(dc)(),
493 > HistoryHostLevelCacheMaxSize: dynamicconfig.HistoryCacheHostLevelMaxSize.Get(dc),
494 > HistoryHostLevelCacheMaxSizeBytes: dynamicconfig.HistoryCacheHostLevelMaxSizeBytes.Get(dc),
495 > HistoryCacheTTL: dynamicconfig.HistoryCacheTTL.Get(dc),
496 > HistoryCacheNonUserContextLockTimeout: dynamicconfig.HistoryCacheNonUserContextLockTimeout.Get(dc),
497 > HistoryCacheBackgroundEvict: dynamicconfig.HistoryCacheBackgroundEvict.Get(dc),
498 > EnableWorkflowExecutionTimeoutTimer: dynamicconfig.EnableWorkflowExecutionTimeoutTimer.Get(dc),
499 > EnableUpdateWorkflowModeIgnoreCurrent: dynamicconfig.EnableUpdateWorkflowModeIgnoreCurrent.Get(dc),
500 > EnableTransitionHistory: dynamicconfig.EnableTransitionHistory.Get(dc),
501 > MaxCallbacksPerWorkflow: dynamicconfig.MaxCallbacksPerWorkflow.Get(dc),
502 > MaxCallbacksPerExecution: callback.MaxPerExecution.Get(dc),
503 > MaxCallbacksPerUpdateID: dynamicconfig.MaxCallbacksPerUpdateID.Get(dc),
504 > EnableChasm: dynamicconfig.EnableChasm.Get(dc),
505 > EnableChasmNexusWorkflowOperations: nexusoperation.EnableChasmWorkflowOperations.Get(dc),
506 > ChasmMaxInMemoryPureTasks: dynamicconfig.ChasmMaxInMemoryPureTasks.Get(dc),
507 >
508 > EnableCHASMSchedulerCreation: dynamicconfig.EnableCHASMSchedulerCreation.Get(dc),
509 > EnableCHASMSchedulerMigration: dynamicconfig.EnableCHASMSchedulerMigration.Get(dc),
510 >
511 > EnableCHASMCallbacks: dynamicconfig.EnableCHASMCallbacks.Get(dc),
512 > EnableCHASMSignalBacklinks: dynamicconfig.EnableCHASMSignalBacklinks.Get(dc),
513 > ExternalPayloadsEnabled: dynamicconfig.ExternalPayloadsEnabled.Get(dc),
514 > EnableWorkflowUpdateCallbacks: dynamicconfig.EnableWorkflowUpdateCallbacks.Get(dc),
515 >
516 > EventsShardLevelCacheMaxSizeBytes: dynamicconfig.EventsCacheMaxSizeBytes.Get(dc), // 512KB
517 > EventsHostLevelCacheMaxSizeBytes: dynamicconfig.EventsHostLevelCacheMaxSizeBytes.Get(dc), // 256MB
518 > EventsCacheTTL: dynamicconfig.EventsCacheTTL.Get(dc),
519 > EnableHostLevelEventsCache: dynamicconfig.EnableHostLevelEventsCache.Get(dc),
520 >
521 > RangeSizeBits: 20, // 20 bits for sequencer, 2^20 sequence number for any range
522 >
523 > AcquireShardInterval: dynamicconfig.AcquireShardInterval.Get(dc),
524 > AcquireShardConcurrency: dynamicconfig.AcquireShardConcurrency.Get(dc),
525 > ShardIOConcurrency: dynamicconfig.ShardIOConcurrency.Get(dc),
526 > ShardIOTimeout: dynamicconfig.ShardIOTimeout.Get(dc),
527 > ShardLingerOwnershipCheckQPS: dynamicconfig.ShardLingerOwnershipCheckQPS.Get(dc),
528 > ShardLingerTimeLimit: dynamicconfig.ShardLingerTimeLimit.Get(dc),
529 > ShardFinalizerTimeout: dynamicconfig.ShardFinalizerTimeout.Get(dc),
530 >
531 > HistoryClientOwnershipCachingEnabled: dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc),
532 >
533 > StandbyClusterDelay: dynamicconfig.StandbyClusterDelay.Get(dc),
534 > StandbyTaskMissingEventsResendDelay: dynamicconfig.StandbyTaskMissingEventsResendDelay.Get(dc),
535 > StandbyTaskMissingEventsDiscardDelay: dynamicconfig.StandbyTaskMissingEventsDiscardDelay.Get(dc),
536 > ChasmStandbyTaskDiscardDelay: dynamicconfig.ChasmStandbyTaskDiscardDelay.Get(dc),
537 >
538 > QueuePendingTaskCriticalCount: dynamicconfig.QueuePendingTaskCriticalCount.Get(dc),
539 > QueueReaderStuckCriticalAttempts: dynamicconfig.QueueReaderStuckCriticalAttempts.Get(dc),
540 > QueueCriticalSlicesCount: dynamicconfig.QueueCriticalSlicesCount.Get(dc),
541 > QueuePendingTaskMaxCount: dynamicconfig.QueuePendingTaskMaxCount.Get(dc),
542 > QueueMaxPredicateSize: dynamicconfig.QueueMaxPredicateSize.Get(dc),
543 > QueueShrinkPredicateMaxPendingKeys: dynamicconfig.QueueShrinkPredicateMaxPendingKeys.Get(dc),
544 > QueueMoveGroupTaskCountBase: dynamicconfig.QueueMoveGroupTaskCountBase.Get(dc),
545 > QueueMoveGroupTaskCountMultiplier: dynamicconfig.QueueMoveGroupTaskCountMultiplier.Get(dc),
546 >
547 > TaskDLQEnabled: dynamicconfig.HistoryTaskDLQEnabled.Get(dc),
548 > TaskDLQUnexpectedErrorAttempts: dynamicconfig.HistoryTaskDLQUnexpectedErrorAttempts.Get(dc),
549 > TaskDLQInternalErrors: dynamicconfig.HistoryTaskDLQInternalErrors.Get(dc),
550 > TaskDLQErrorPattern: dynamicconfig.HistoryTaskDLQErrorPattern.Get(dc),
551 >
552 > TaskSchedulerEnableRateLimiter: dynamicconfig.TaskSchedulerEnableRateLimiter.Get(dc),
553 > TaskSchedulerEnableRateLimiterShadowMode: dynamicconfig.TaskSchedulerEnableRateLimiterShadowMode.Get(dc),
554 > TaskSchedulerRateLimiterStartupDelay: dynamicconfig.TaskSchedulerRateLimiterStartupDelay.Get(dc),
555 > TaskSchedulerGlobalMaxQPS: dynamicconfig.TaskSchedulerGlobalMaxQPS.Get(dc),
556 > TaskSchedulerMaxQPS: dynamicconfig.TaskSchedulerMaxQPS.Get(dc),
557 > TaskSchedulerNamespaceMaxQPS: dynamicconfig.TaskSchedulerNamespaceMaxQPS.Get(dc),
558 > TaskSchedulerGlobalNamespaceMaxQPS: dynamicconfig.TaskSchedulerGlobalNamespaceMaxQPS.Get(dc),
559 > TaskSchedulerInactiveChannelDeletionDelay: dynamicconfig.TaskSchedulerInactiveChannelDeletionDelay.Get(dc),
560 > TaskSchedulerEnableExecutionQueueScheduler: dynamicconfig.TaskSchedulerEnableExecutionQueueScheduler.Get(dc),
561 > TaskSchedulerExecutionQueueSchedulerMaxQueues: dynamicconfig.TaskSchedulerExecutionQueueSchedulerMaxQueues.Get(dc),
562 > TaskSchedulerExecutionQueueSchedulerQueueTTL: dynamicconfig.TaskSchedulerExecutionQueueSchedulerQueueTTL.Get(dc),
563 > TaskSchedulerExecutionQueueSchedulerQueueConcurrency: dynamicconfig.TaskSchedulerExecutionQueueSchedulerQueueConcurrency.Get(dc),
564 >
565 > TimerTaskBatchSize: dynamicconfig.TimerTaskBatchSize.Get(dc),
566 > TimerProcessorSchedulerWorkerCount: dynamicconfig.TimerProcessorSchedulerWorkerCount.Subscribe(dc),
567 > TimerProcessorSchedulerActiveRoundRobinWeights: dynamicconfig.TimerProcessorSchedulerActiveRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultActiveTaskPriorityWeight)).Get(dc),
568 > TimerProcessorSchedulerStandbyRoundRobinWeights: dynamicconfig.TimerProcessorSchedulerStandbyRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultStandbyTaskPriorityWeight)).Get(dc),
569 > TimerProcessorUpdateAckInterval: dynamicconfig.TimerProcessorUpdateAckInterval.Get(dc),
570 > TimerProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.TimerProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
571 > TimerProcessorMaxPollRPS: dynamicconfig.TimerProcessorMaxPollRPS.Get(dc),
572 > TimerProcessorMaxPollHostRPS: dynamicconfig.TimerProcessorMaxPollHostRPS.Get(dc),
573 > TimerProcessorMaxPollInterval: dynamicconfig.TimerProcessorMaxPollInterval.Get(dc),
574 > TimerProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.TimerProcessorMaxPollIntervalJitterCoefficient.Get(dc),
575 > TimerProcessorPollBackoffInterval: dynamicconfig.TimerProcessorPollBackoffInterval.Get(dc),
576 > TimerProcessorMaxTimeShift: dynamicconfig.TimerProcessorMaxTimeShift.Get(dc),
577 > TransferQueueMaxReaderCount: dynamicconfig.TransferQueueMaxReaderCount.Get(dc),
578 > RetentionTimerJitterDuration: dynamicconfig.RetentionTimerJitterDuration.Get(dc),
579 >
580 > MemoryTimerProcessorSchedulerWorkerCount: dynamicconfig.MemoryTimerProcessorSchedulerWorkerCount.Subscribe(dc),
581 >
582 > TransferTaskBatchSize: dynamicconfig.TransferTaskBatchSize.Get(dc),
583 > TransferProcessorSchedulerWorkerCount: dynamicconfig.TransferProcessorSchedulerWorkerCount.Subscribe(dc),
584 > TransferProcessorSchedulerActiveRoundRobinWeights: dynamicconfig.TransferProcessorSchedulerActiveRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultActiveTaskPriorityWeight)).Get(dc),
585 > TransferProcessorSchedulerStandbyRoundRobinWeights: dynamicconfig.TransferProcessorSchedulerStandbyRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultStandbyTaskPriorityWeight)).Get(dc),
586 > TransferProcessorMaxPollRPS: dynamicconfig.TransferProcessorMaxPollRPS.Get(dc),
587 > TransferProcessorMaxPollHostRPS: dynamicconfig.TransferProcessorMaxPollHostRPS.Get(dc),
588 > TransferProcessorMaxPollInterval: dynamicconfig.TransferProcessorMaxPollInterval.Get(dc),
589 > TransferProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.TransferProcessorMaxPollIntervalJitterCoefficient.Get(dc),
590 > TransferProcessorUpdateAckInterval: dynamicconfig.TransferProcessorUpdateAckInterval.Get(dc),
591 > TransferProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.TransferProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
592 > TransferProcessorPollBackoffInterval: dynamicconfig.TransferProcessorPollBackoffInterval.Get(dc),
593 > TransferProcessorEnsureCloseBeforeDelete: dynamicconfig.TransferProcessorEnsureCloseBeforeDelete.Get(dc),
594 > TimerQueueMaxReaderCount: dynamicconfig.TimerQueueMaxReaderCount.Get(dc),
595 >
596 > OutboundTaskBatchSize: dynamicconfig.OutboundTaskBatchSize.Get(dc),
597 > OutboundProcessorMaxPollRPS: dynamicconfig.OutboundProcessorMaxPollRPS.Get(dc),
598 > OutboundProcessorMaxPollHostRPS: dynamicconfig.OutboundProcessorMaxPollHostRPS.Get(dc),
599 > OutboundProcessorMaxPollInterval: dynamicconfig.OutboundProcessorMaxPollInterval.Get(dc),
600 > OutboundProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.OutboundProcessorMaxPollIntervalJitterCoefficient.Get(dc),
601 > OutboundProcessorUpdateAckInterval: dynamicconfig.OutboundProcessorUpdateAckInterval.Get(dc),
602 > OutboundProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.OutboundProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
603 > OutboundProcessorPollBackoffInterval: dynamicconfig.OutboundProcessorPollBackoffInterval.Get(dc),
604 > OutboundQueuePendingTaskCriticalCount: dynamicconfig.OutboundQueuePendingTaskCriticalCount.Get(dc),
605 > OutboundQueuePendingTaskMaxCount: dynamicconfig.OutboundQueuePendingTaskMaxCount.Get(dc),
606 > OutboundQueueMaxPredicateSize: dynamicconfig.OutboundQueueMaxPredicateSize.Get(dc),
607 > OutboundQueueMaxReaderCount: dynamicconfig.OutboundQueueMaxReaderCount.Get(dc),
608 > OutboundQueueGroupLimiterBufferSize: dynamicconfig.OutboundQueueGroupLimiterBufferSize.Get(dc),
609 > OutboundQueueGroupLimiterConcurrency: dynamicconfig.OutboundQueueGroupLimiterConcurrency.Get(dc),
610 > OutboundQueueHostSchedulerMaxTaskRPS: dynamicconfig.OutboundQueueHostSchedulerMaxTaskRPS.Get(dc),
611 > OutboundQueueCircuitBreakerSettings: dynamicconfig.OutboundQueueCircuitBreakerSettings.Subscribe(dc),
612 > OutboundStandbyTaskMissingEventsDestinationDownErr: dynamicconfig.OutboundStandbyTaskMissingEventsDestinationDownErr.Get(dc),
613 > OutboundStandbyTaskMissingEventsDiscardDelay: dynamicconfig.OutboundStandbyTaskMissingEventsDiscardDelay.Get(dc),
614 >
615 > ReplicatorProcessorMaxPollInterval: dynamicconfig.ReplicatorProcessorMaxPollInterval.Get(dc),
616 > ReplicatorProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.ReplicatorProcessorMaxPollIntervalJitterCoefficient.Get(dc),
617 > ReplicatorProcessorFetchTasksBatchSize: dynamicconfig.ReplicatorTaskBatchSize.Get(dc),
618 > ReplicatorProcessorMaxSkipTaskCount: dynamicconfig.ReplicatorMaxSkipTaskCount.Get(dc),
619 > ReplicationTaskProcessorHostQPS: dynamicconfig.ReplicationTaskProcessorHostQPS.Get(dc),
620 > ReplicationTaskProcessorShardQPS: dynamicconfig.ReplicationTaskProcessorShardQPS.Get(dc),
621 > ReplicationEnableDLQMetrics: dynamicconfig.ReplicationEnableDLQMetrics.Get(dc),
622 > ReplicationEnableUpdateWithNewTaskMerge: dynamicconfig.ReplicationEnableUpdateWithNewTaskMerge.Get(dc),
623 > ReplicationStreamSyncStatusDuration: dynamicconfig.ReplicationStreamSyncStatusDuration.Get(dc),
624 > ReplicationProcessorSchedulerQueueSize: dynamicconfig.ReplicationProcessorSchedulerQueueSize.Get(dc),
625 > ReplicationProcessorSchedulerWorkerCount: dynamicconfig.ReplicationProcessorSchedulerWorkerCount.Subscribe(dc),
626 > ReplicationLowPriorityProcessorSchedulerWorkerCount: dynamicconfig.ReplicationLowPriorityProcessorSchedulerWorkerCount.Subscribe(dc),
627 > ReplicationLowPriorityTaskParallelism: dynamicconfig.ReplicationLowPriorityTaskParallelism.Get(dc),
628 > EnableReplicationTaskBatching: dynamicconfig.EnableReplicationTaskBatching.Get(dc),
629 > EnableReplicationTaskTieredProcessing: dynamicconfig.EnableReplicationTaskTieredProcessing.Get(dc),
630 > ReplicationStreamSenderHighPriorityQPS: dynamicconfig.ReplicationStreamSenderHighPriorityQPS.Get(dc),
631 > ReplicationStreamSenderLowPriorityQPS: dynamicconfig.ReplicationStreamSenderLowPriorityQPS.Get(dc),
632 > ReplicationStreamEventLoopRetryMaxAttempts: dynamicconfig.ReplicationStreamEventLoopRetryMaxAttempts.Get(dc),
633 > ReplicationReceiverMaxOutstandingTaskCount: dynamicconfig.ReplicationReceiverMaxOutstandingTaskCount.Get(dc),
634 > ReplicationReceiverSlowSubmissionLatencyThreshold: dynamicconfig.ReplicationReceiverSlowSubmissionLatencyThreshold.Get(dc),
635 > ReplicationReceiverSlowSubmissionWindow: dynamicconfig.ReplicationReceiverSlowSubmissionWindow.Get(dc),
636 > EnableReplicationReceiverSlowSubmissionFlowControl: dynamicconfig.EnableReplicationReceiverSlowSubmissionFlowControl.Get(dc),
637 > ReplicationResendMaxBatchCount: dynamicconfig.ReplicationResendMaxBatchCount.Get(dc),
638 > ReplicationProgressCacheMaxSize: dynamicconfig.ReplicationProgressCacheMaxSize.Get(dc),
639 > ReplicationProgressCacheTTL: dynamicconfig.ReplicationProgressCacheTTL.Get(dc),
640 > ReplicationEnableRateLimit: dynamicconfig.ReplicationEnableRateLimit.Get(dc),
641 > ReplicationEnableRateLimitShadowMode: dynamicconfig.ReplicationEnableRateLimitShadowMode.Get(dc),
642 > ReplicationStreamSendEmptyTaskDuration: dynamicconfig.ReplicationStreamSendEmptyTaskDuration.Get(dc),
643 > ReplicationStreamReceiverLivenessMultiplier: dynamicconfig.ReplicationStreamReceiverLivenessMultiplier.Get(dc),
644 > ReplicationStreamSenderLivenessMultiplier: dynamicconfig.ReplicationStreamSenderLivenessMultiplier.Get(dc),
645 > EnableHistoryReplicationRateLimiter: dynamicconfig.EnableHistoryReplicationRateLimiter.Get(dc),
646 >
647 > MaximumBufferedEventsBatch: dynamicconfig.MaximumBufferedEventsBatch.Get(dc),
648 > MaximumBufferedEventsSizeInBytes: dynamicconfig.MaximumBufferedEventsSizeInBytes.Get(dc),
649 > MaximumSignalsPerExecution: dynamicconfig.MaximumSignalsPerExecution.Get(dc),
650 > MaximumEventBatchSizeInBytes: dynamicconfig.MaximumEventBatchSizeInBytes.Get(dc),
651 > ShardUpdateMinInterval: dynamicconfig.ShardUpdateMinInterval.Get(dc),
652 > ShardFirstUpdateInterval: dynamicconfig.ShardFirstUpdateInterval.Get(dc),
653 > ShardUpdateMinTasksCompleted: dynamicconfig.ShardUpdateMinTasksCompleted.Get(dc),
654 > ShardSyncMinInterval: dynamicconfig.ShardSyncMinInterval.Get(dc),
655 > ShardSyncTimerJitterCoefficient: dynamicconfig.TransferProcessorMaxPollIntervalJitterCoefficient.Get(dc),
656 >
657 > // history client: client/history/client.go set the client timeout 30s
658 > // TODO: Return this value to the client: go.temporal.io/server/issues/294
659 > LongPollExpirationInterval: dynamicconfig.HistoryLongPollExpirationInterval.Get(dc),
660 > EnableParentClosePolicy: dynamicconfig.EnableParentClosePolicy.Get(dc),
661 > NumParentClosePolicySystemWorkflows: dynamicconfig.NumParentClosePolicySystemWorkflows.Get(dc),
662 > EnableParentClosePolicyWorker: dynamicconfig.EnableParentClosePolicyWorker.Get(dc),
663 > ParentClosePolicyThreshold: dynamicconfig.ParentClosePolicyThreshold.Get(dc),
664 >
665 > BlobSizeLimitError: dynamicconfig.BlobSizeLimitError.Get(dc),
666 > BlobSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
667 > MemoSizeLimitError: dynamicconfig.MemoSizeLimitError.Get(dc),
668 > MemoSizeLimitWarn: dynamicconfig.MemoSizeLimitWarn.Get(dc),
669 > NumPendingChildExecutionsLimit: dynamicconfig.NumPendingChildExecutionsLimitError.Get(dc),
670 > NumPendingActivitiesLimit: dynamicconfig.NumPendingActivitiesLimitError.Get(dc),
671 > NumPendingSignalsLimit: dynamicconfig.NumPendingSignalsLimitError.Get(dc),
672 > NumPendingCancelsRequestLimit: dynamicconfig.NumPendingCancelRequestsLimitError.Get(dc),
673 > HistorySizeLimitError: dynamicconfig.HistorySizeLimitError.Get(dc),
674 > HistorySizeLimitWarn: dynamicconfig.HistorySizeLimitWarn.Get(dc),
675 > HistorySizeSuggestContinueAsNew: dynamicconfig.HistorySizeSuggestContinueAsNew.Get(dc),
676 > HistoryCountLimitError: dynamicconfig.HistoryCountLimitError.Get(dc),
677 > HistoryCountLimitWarn: dynamicconfig.HistoryCountLimitWarn.Get(dc),
678 > HistoryCountSuggestContinueAsNew: dynamicconfig.HistoryCountSuggestContinueAsNew.Get(dc),
679 > HistoryMaxPageSize: dynamicconfig.HistoryMaxPageSize.Get(dc),
680 > MutableStateActivityFailureSizeLimitError: dynamicconfig.MutableStateActivityFailureSizeLimitError.Get(dc),
681 > MutableStateActivityFailureSizeLimitWarn: dynamicconfig.MutableStateActivityFailureSizeLimitWarn.Get(dc),
682 > MutableStateSizeLimitError: dynamicconfig.MutableStateSizeLimitError.Get(dc),
683 > MutableStateSizeLimitWarn: dynamicconfig.MutableStateSizeLimitWarn.Get(dc),
684 > MutableStateTombstoneCountLimit: dynamicconfig.MutableStateTombstoneCountLimit.Get(dc),
685 >
686 > ThrottledLogRPS: dynamicconfig.HistoryThrottledLogRPS.Get(dc),
687 > EnableStickyQuery: dynamicconfig.EnableStickyQuery.Get(dc),
688 >
689 > DefaultActivityRetryPolicy: dynamicconfig.DefaultActivityRetryPolicy.Get(dc),
690 > DefaultWorkflowRetryPolicy: dynamicconfig.DefaultWorkflowRetryPolicy.Get(dc),
691 > WorkflowTaskHeartbeatTimeout: dynamicconfig.WorkflowTaskHeartbeatTimeout.Get(dc),
692 > WorkflowTaskCriticalAttempts: dynamicconfig.WorkflowTaskCriticalAttempts.Get(dc),
693 > WorkflowTaskRetryMaxInterval: dynamicconfig.WorkflowTaskRetryMaxInterval.Get(dc),
694 > EnableWorkflowTaskStampIncrementOnFailure: dynamicconfig.EnableWorkflowTaskStampIncrementOnFailure.Get(dc),
695 > DiscardSpeculativeWorkflowTaskMaximumEventsCount: dynamicconfig.DiscardSpeculativeWorkflowTaskMaximumEventsCount.Get(dc),
696 > EnableDropRepeatedWorkflowTaskFailures: dynamicconfig.EnableDropRepeatedWorkflowTaskFailures.Get(dc),
697 > SendTransientOrSpeculativeWorkflowTaskEvents: dynamicconfig.SendTransientOrSpeculativeWorkflowTaskEvents.Get(dc),
698 >
699 > ReplicationTaskApplyTimeout: dynamicconfig.ReplicationTaskApplyTimeout.Get(dc),
700 > ReplicationTaskFetcherParallelism: dynamicconfig.ReplicationTaskFetcherParallelism.Get(dc),
701 > ReplicationTaskFetcherAggregationInterval: dynamicconfig.ReplicationTaskFetcherAggregationInterval.Get(dc),
702 > ReplicationTaskFetcherTimerJitterCoefficient: dynamicconfig.ReplicationTaskFetcherTimerJitterCoefficient.Get(dc),
703 > ReplicationTaskFetcherErrorRetryWait: dynamicconfig.ReplicationTaskFetcherErrorRetryWait.Get(dc),
704 >
705 > ReplicationTaskProcessorErrorRetryWait: dynamicconfig.ReplicationTaskProcessorErrorRetryWait.Get(dc),
706 > ReplicationTaskProcessorErrorRetryBackoffCoefficient: dynamicconfig.ReplicationTaskProcessorErrorRetryBackoffCoefficient.Get(dc),
707 > ReplicationTaskProcessorErrorRetryMaxInterval: dynamicconfig.ReplicationTaskProcessorErrorRetryMaxInterval.Get(dc),
708 > ReplicationTaskProcessorErrorRetryMaxAttempts: dynamicconfig.ReplicationTaskProcessorErrorRetryMaxAttempts.Get(dc),
709 > ReplicationTaskProcessorErrorRetryExpiration: dynamicconfig.ReplicationTaskProcessorErrorRetryExpiration.Get(dc),
710 > ReplicationTaskProcessorNoTaskRetryWait: dynamicconfig.ReplicationTaskProcessorNoTaskInitialWait.Get(dc),
711 > ReplicationTaskProcessorCleanupInterval: dynamicconfig.ReplicationTaskProcessorCleanupInterval.Get(dc),
712 > ReplicationTaskProcessorCleanupJitterCoefficient: dynamicconfig.ReplicationTaskProcessorCleanupJitterCoefficient.Get(dc),
713 > ReplicationMultipleBatches: dynamicconfig.ReplicationMultipleBatches.Get(dc),
714 >
715 > ReplicationStreamSenderErrorRetryWait: dynamicconfig.ReplicationStreamSenderErrorRetryWait.Get(dc),
716 > ReplicationStreamSenderErrorRetryBackoffCoefficient: dynamicconfig.ReplicationStreamSenderErrorRetryBackoffCoefficient.Get(dc),
717 > ReplicationStreamSenderErrorRetryMaxInterval: dynamicconfig.ReplicationStreamSenderErrorRetryMaxInterval.Get(dc),
718 > ReplicationStreamSenderErrorRetryMaxAttempts: dynamicconfig.ReplicationStreamSenderErrorRetryMaxAttempts.Get(dc),
719 > ReplicationStreamSenderErrorRetryExpiration: dynamicconfig.ReplicationStreamSenderErrorRetryExpiration.Get(dc),
720 >
721 > ReplicationExecutableTaskErrorRetryWait: dynamicconfig.ReplicationExecutableTaskErrorRetryWait.Get(dc),
722 > ReplicationExecutableTaskErrorRetryBackoffCoefficient: dynamicconfig.ReplicationExecutableTaskErrorRetryBackoffCoefficient.Get(dc),
723 > ReplicationExecutableTaskErrorRetryMaxInterval: dynamicconfig.ReplicationExecutableTaskErrorRetryMaxInterval.Get(dc),
724 > ReplicationExecutableTaskErrorRetryMaxAttempts: dynamicconfig.ReplicationExecutableTaskErrorRetryMaxAttempts.Get(dc),
725 > ReplicationExecutableTaskErrorRetryExpiration: dynamicconfig.ReplicationExecutableTaskErrorRetryExpiration.Get(dc),
726 >
727 > MaxBufferedQueryCount: dynamicconfig.MaxBufferedQueryCount.Get(dc),
728 > MutableStateChecksumGenProbability: dynamicconfig.MutableStateChecksumGenProbability.Get(dc),
729 > MutableStateChecksumVerifyProbability: dynamicconfig.MutableStateChecksumVerifyProbability.Get(dc),
730 > MutableStateChecksumInvalidateBefore: dynamicconfig.MutableStateChecksumInvalidateBefore.Get(dc),
731 >
732 > StandbyTaskReReplicationContextTimeout: dynamicconfig.StandbyTaskReReplicationContextTimeout.Get(dc),
733 >
734 > SkipReapplicationByNamespaceID: dynamicconfig.SkipReapplicationByNamespaceID.Get(dc),
735 >
736 > // ===== Visibility related =====
737 > VisibilityTaskBatchSize: dynamicconfig.VisibilityTaskBatchSize.Get(dc),
738 > VisibilityProcessorMaxPollRPS: dynamicconfig.VisibilityProcessorMaxPollRPS.Get(dc),
739 > VisibilityProcessorMaxPollHostRPS: dynamicconfig.VisibilityProcessorMaxPollHostRPS.Get(dc),
740 > VisibilityProcessorSchedulerWorkerCount: dynamicconfig.VisibilityProcessorSchedulerWorkerCount.Subscribe(dc),
741 > VisibilityProcessorSchedulerActiveRoundRobinWeights: dynamicconfig.VisibilityProcessorSchedulerActiveRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultActiveTaskPriorityWeight)).Get(dc),
742 > VisibilityProcessorSchedulerStandbyRoundRobinWeights: dynamicconfig.VisibilityProcessorSchedulerStandbyRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultStandbyTaskPriorityWeight)).Get(dc),
743 > VisibilityProcessorMaxPollInterval: dynamicconfig.VisibilityProcessorMaxPollInterval.Get(dc),
744 > VisibilityProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.VisibilityProcessorMaxPollIntervalJitterCoefficient.Get(dc),
745 > VisibilityProcessorUpdateAckInterval: dynamicconfig.VisibilityProcessorUpdateAckInterval.Get(dc),
746 > VisibilityProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.VisibilityProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
747 > VisibilityProcessorPollBackoffInterval: dynamicconfig.VisibilityProcessorPollBackoffInterval.Get(dc),
748 > VisibilityProcessorEnsureCloseBeforeDelete: dynamicconfig.VisibilityProcessorEnsureCloseBeforeDelete.Get(dc),
749 > VisibilityProcessorEnableCloseWorkflowCleanup: dynamicconfig.VisibilityProcessorEnableCloseWorkflowCleanup.Get(dc),
750 > VisibilityProcessorRelocateAttributesMinBlobSize: dynamicconfig.VisibilityProcessorRelocateAttributesMinBlobSize.Get(dc),
751 > VisibilityQueueMaxReaderCount: dynamicconfig.VisibilityQueueMaxReaderCount.Get(dc),
752 >
753 > DisableFetchRelocatableAttributesFromVisibility: dynamicconfig.DisableFetchRelocatableAttributesFromVisibility.Get(dc),
754 >
755 > SearchAttributesNumberOfKeysLimit: dynamicconfig.SearchAttributesNumberOfKeysLimit.Get(dc),
756 > SearchAttributesSizeOfValueLimit: dynamicconfig.SearchAttributesSizeOfValueLimit.Get(dc),
757 > SearchAttributesTotalSizeLimit: dynamicconfig.SearchAttributesTotalSizeLimit.Get(dc),
758 > IndexerConcurrency: dynamicconfig.WorkerIndexerConcurrency.Get(dc),
759 > ESProcessorNumOfWorkers: dynamicconfig.WorkerESProcessorNumOfWorkers.Get(dc),
760 > // Should not be greater than number of visibility task queue workers VisibilityProcessorSchedulerWorkerCount (default 512)
761 > // Otherwise, visibility queue processors won't be able to fill up bulk with documents (even under heavy load) and bulk will flush due to interval, not number of actions.
762 > ESProcessorBulkActions: dynamicconfig.WorkerESProcessorBulkActions.Get(dc),
763 > // 16MB - just a sanity check. With ES document size ~1Kb it should never be reached.
764 > ESProcessorBulkSize: dynamicconfig.WorkerESProcessorBulkSize.Get(dc),
765 > // Bulk processor will flush every this interval regardless of last flush due to bulk actions.
766 > ESProcessorFlushInterval: dynamicconfig.WorkerESProcessorFlushInterval.Get(dc),
767 > ESProcessorAckTimeout: dynamicconfig.WorkerESProcessorAckTimeout.Get(dc),
768 >
769 > EnableCrossNamespaceCommands: dynamicconfig.EnableCrossNamespaceCommands.Get(dc),
770 > EnableActivityEagerExecution: dynamicconfig.EnableActivityEagerExecution.Get(dc),
771 > EnableActivityRetryStampIncrement: dynamicconfig.EnableActivityRetryStampIncrement.Get(dc),
772 > EnableCancelActivityWorkerCommand: dynamicconfig.EnableCancelActivityWorkerCommand.Get(dc),
773 > EnableEagerWorkflowStart: dynamicconfig.EnableEagerWorkflowStart.Get(dc),
774 > NamespaceCacheRefreshInterval: dynamicconfig.NamespaceCacheRefreshInterval.Get(dc),
775 >
776 > // Archival related
777 > ArchivalTaskBatchSize: dynamicconfig.ArchivalTaskBatchSize.Get(dc),
778 > ArchivalProcessorMaxPollRPS: dynamicconfig.ArchivalProcessorMaxPollRPS.Get(dc),
779 > ArchivalProcessorMaxPollHostRPS: dynamicconfig.ArchivalProcessorMaxPollHostRPS.Get(dc),
780 > ArchivalProcessorSchedulerWorkerCount: dynamicconfig.ArchivalProcessorSchedulerWorkerCount.Subscribe(dc),
781 > ArchivalProcessorMaxPollInterval: dynamicconfig.ArchivalProcessorMaxPollInterval.Get(dc),
782 > ArchivalProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.ArchivalProcessorMaxPollIntervalJitterCoefficient.Get(dc),
783 > ArchivalProcessorUpdateAckInterval: dynamicconfig.ArchivalProcessorUpdateAckInterval.Get(dc),
784 > ArchivalProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.ArchivalProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
785 > ArchivalProcessorPollBackoffInterval: dynamicconfig.ArchivalProcessorPollBackoffInterval.Get(dc),
786 > ArchivalProcessorArchiveDelay: dynamicconfig.ArchivalProcessorArchiveDelay.Get(dc),
787 > ArchivalBackendMaxRPS: dynamicconfig.ArchivalBackendMaxRPS.Get(dc),
788 > ArchivalQueueMaxReaderCount: dynamicconfig.ArchivalQueueMaxReaderCount.Get(dc),
789 >
790 > // workflow update related
791 > WorkflowExecutionMaxInFlightUpdates: dynamicconfig.WorkflowExecutionMaxInFlightUpdates.Get(dc),
792 > WorkflowExecutionMaxInFlightUpdatePayloads: dynamicconfig.WorkflowExecutionMaxInFlightUpdatePayloads.Get(dc),
793 > WorkflowExecutionMaxTotalUpdates: dynamicconfig.WorkflowExecutionMaxTotalUpdates.Get(dc),
794 > WorkflowExecutionMaxTotalUpdatesSuggestContinueAsNewThreshold: dynamicconfig.WorkflowExecutionMaxTotalUpdatesSuggestContinueAsNewThreshold.Get(dc),
795 > EnableUpdateWithStartRetryOnClosedWorkflowAbort: dynamicconfig.EnableUpdateWithStartRetryOnClosedWorkflowAbort.Get(dc),
796 > EnableUpdateWithStartRetryableErrorOnClosedWorkflowAbort: dynamicconfig.EnableUpdateWithStartRetryableErrorOnClosedWorkflowAbort.Get(dc),
797 >
798 > SendRawHistoryBetweenInternalServices: dynamicconfig.SendRawHistoryBetweenInternalServices.Get(dc),
799 > SendRawHistoryBytesToMatchingService: dynamicconfig.SendRawHistoryBytesToMatchingService.Get(dc),
800 > SendRawWorkflowHistory: dynamicconfig.SendRawWorkflowHistory.Get(dc),
801 > WorkflowIdReuseMinimalInterval: dynamicconfig.WorkflowIdReuseMinimalInterval.Get(dc),
802 > EnableWorkflowIdReuseStartTimeValidation: dynamicconfig.EnableWorkflowIdReuseStartTimeValidation.Get(dc),
803 > BusinessIDReuseRate: dynamicconfig.BusinessIDReuseRate.Get(dc),
804 > BusinessIDReuseBurstRatio: dynamicconfig.BusinessIDReuseBurstRatio.Get(dc),
805 > BusinessIDReuseLimiterCacheSize: dynamicconfig.BusinessIDReuseLimiterCacheSize.Get(dc),
806 > BusinessIDReuseLimiterCacheTTL: dynamicconfig.BusinessIDReuseLimiterCacheTTL.Get(dc),
807 >
808 > HealthPersistenceLatencyFailure: dynamicconfig.HealthPersistenceLatencyFailure.Get(dc),
809 > HealthPersistenceLatencyPercentiles: dynamicconfig.PersistenceHealthSignalPercentileLatencySettings.Get(dc),
810 > HealthPersistenceErrorRatio: dynamicconfig.HealthPersistenceErrorRatio.Get(dc),
811 > HealthRPCLatencyFailure: dynamicconfig.HealthRPCLatencyFailure.Get(dc),
812 > HealthRPCLatencyPercentiles: dynamicconfig.HistoryHealthSignalPercentileLatencySettings.Get(dc),
813 > HealthRPCErrorRatio: dynamicconfig.HealthRPCErrorRatio.Get(dc),
814 > HealthHistoryInitializationTime: dynamicconfig.HealthHistoryInitializationTime.Get(dc),
815 >
816 > BreakdownMetricsByTaskQueue: dynamicconfig.MetricsBreakdownByTaskQueue.Get(dc),
817 >
818 > LogAllReqErrors: dynamicconfig.LogAllReqErrors.Get(dc),
819 >
820 > NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute: dynamicconfig.NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute.Get(dc),
821 >
822 > // Worker-Versioning related
823 > UseRevisionNumberForWorkerVersioning: dynamicconfig.UseRevisionNumberForWorkerVersioning.Get(dc),
824 > EnableSuggestCaNOnNewTargetVersion: dynamicconfig.EnableSuggestCaNOnNewTargetVersion.Get(dc),
825 > EnableSendTargetVersionChanged: dynamicconfig.EnableSendTargetVersionChanged.Get(dc),
826 > VersionMembershipCacheTTL: dynamicconfig.VersionMembershipCacheTTL.Get(dc),
827 > VersionMembershipCacheMaxSize: dynamicconfig.VersionMembershipCacheMaxSize.Get(dc),
828 > EnableVersionReactivationSignals: dynamicconfig.EnableVersionReactivationSignals.Get(dc),
829 > RoutingInfoCacheTTL: dynamicconfig.RoutingInfoCacheTTL.Get(dc),
830 > RoutingInfoCacheMaxSize: dynamicconfig.RoutingInfoCacheMaxSize.Get(dc),
831 >
832 > // Workflow task completion pagination
833 > EnableWorkflowTaskCompletionPagination: dynamicconfig.EnableWorkflowTaskCompletionPagination.Get(dc),
834 > WorkflowTaskCompletionBufferSizeLimit: dynamicconfig.WorkflowTaskCompletionBufferSizeLimit.Get(dc),
835 > }
836 >
837 > return cfg
838 > }
839
840 // GetShardID return the corresponding shard ID for a given namespaceID and workflowID pair
go.temporal.io/server/common/dynamicconfig/setting_gen.go 324 covered LOC · 75 ranges

Open complete file

26 type GlobalBoolConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[bool]
27
28 > func NewGlobalBoolSetting(key string, def bool, description string) GlobalBoolSetting { setting_gen.go
29 > return NewGlobalTypedSettingWithConverter[bool](key, convertBool, def, description)
30 > }
31
32 func NewGlobalBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) GlobalBoolConstrainedDefaultSetting {
43 type NamespaceBoolConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[bool]
44
45 > func NewNamespaceBoolSetting(key string, def bool, description string) NamespaceBoolSetting { setting_gen.go
46 > return NewNamespaceTypedSettingWithConverter[bool](key, convertBool, def, description)
47 > }
48
49 func NewNamespaceBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) NamespaceBoolConstrainedDefaultSetting {
53 type BoolPropertyFnWithNamespaceFilter = TypedPropertyFnWithNamespaceFilter[bool]
54
55 > func GetBoolPropertyFnFilteredByNamespace(value bool) BoolPropertyFnWithNamespaceFilter { setting_gen.go
56 > return GetTypedPropertyFnFilteredByNamespace(value)
57 > }
58
59 type NamespaceIDBoolSetting = NamespaceIDTypedSetting[bool]
60 type NamespaceIDBoolConstrainedDefaultSetting = NamespaceIDTypedConstrainedDefaultSetting[bool]
61
62 > func NewNamespaceIDBoolSetting(key string, def bool, description string) NamespaceIDBoolSetting { setting_gen.go
63 > return NewNamespaceIDTypedSettingWithConverter[bool](key, convertBool, def, description)
64 > }
65
66 func NewNamespaceIDBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) NamespaceIDBoolConstrainedDefaultSetting {
77 type TaskQueueBoolConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[bool]
78
79 > func NewTaskQueueBoolSetting(key string, def bool, description string) TaskQueueBoolSetting { setting_gen.go
80 > return NewTaskQueueTypedSettingWithConverter[bool](key, convertBool, def, description)
81 > }
82
83 func NewTaskQueueBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) TaskQueueBoolConstrainedDefaultSetting {
128 type DestinationBoolConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[bool]
129
130 > func NewDestinationBoolSetting(key string, def bool, description string) DestinationBoolSetting { setting_gen.go
131 > return NewDestinationTypedSettingWithConverter[bool](key, convertBool, def, description)
132 > }
133
134 func NewDestinationBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) DestinationBoolConstrainedDefaultSetting {
162 type GlobalIntConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[int]
163
164 > func NewGlobalIntSetting(key string, def int, description string) GlobalIntSetting { setting_gen.go
165 > return NewGlobalTypedSettingWithConverter[int](key, convertInt, def, description)
166 > }
167
168 func NewGlobalIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) GlobalIntConstrainedDefaultSetting {
179 type NamespaceIntConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[int]
180
181 > func NewNamespaceIntSetting(key string, def int, description string) NamespaceIntSetting { setting_gen.go
182 > return NewNamespaceTypedSettingWithConverter[int](key, convertInt, def, description)
183 > }
184
185 func NewNamespaceIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) NamespaceIntConstrainedDefaultSetting {
189 type IntPropertyFnWithNamespaceFilter = TypedPropertyFnWithNamespaceFilter[int]
190
191 > func GetIntPropertyFnFilteredByNamespace(value int) IntPropertyFnWithNamespaceFilter { setting_gen.go
192 > return GetTypedPropertyFnFilteredByNamespace(value)
193 > }
194
195 type NamespaceIDIntSetting = NamespaceIDTypedSetting[int]
213 type TaskQueueIntConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[int]
214
215 > func NewTaskQueueIntSetting(key string, def int, description string) TaskQueueIntSetting { setting_gen.go
216 > return NewTaskQueueTypedSettingWithConverter[int](key, convertInt, def, description)
217 > }
218
219 > func NewTaskQueueIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) TaskQueueIntConstrainedDefaultSetting { setting_gen.go
220 > return NewTaskQueueTypedSettingWithConstrainedDefault[int](key, convertInt, cdef, description)
221 > }
222
223 type IntPropertyFnWithTaskQueueFilter = TypedPropertyFnWithTaskQueueFilter[int]
230 type ShardIDIntConstrainedDefaultSetting = ShardIDTypedConstrainedDefaultSetting[int]
231
232 > func NewShardIDIntSetting(key string, def int, description string) ShardIDIntSetting { setting_gen.go
233 > return NewShardIDTypedSettingWithConverter[int](key, convertInt, def, description)
234 > }
235
236 func NewShardIDIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) ShardIDIntConstrainedDefaultSetting {
264 type DestinationIntConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[int]
265
266 > func NewDestinationIntSetting(key string, def int, description string) DestinationIntSetting { setting_gen.go
267 > return NewDestinationTypedSettingWithConverter[int](key, convertInt, def, description)
268 > }
269
270 func NewDestinationIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) DestinationIntConstrainedDefaultSetting {
298 type GlobalFloatConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[float64]
299
300 > func NewGlobalFloatSetting(key string, def float64, description string) GlobalFloatSetting { setting_gen.go
301 > return NewGlobalTypedSettingWithConverter[float64](key, convertFloat, def, description)
302 > }
303
304 func NewGlobalFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) GlobalFloatConstrainedDefaultSetting {
315 type NamespaceFloatConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[float64]
316
317 > func NewNamespaceFloatSetting(key string, def float64, description string) NamespaceFloatSetting { setting_gen.go
318 > return NewNamespaceTypedSettingWithConverter[float64](key, convertFloat, def, description)
319 > }
320
321 func NewNamespaceFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) NamespaceFloatConstrainedDefaultSetting {
349 type TaskQueueFloatConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[float64]
350
351 > func NewTaskQueueFloatSetting(key string, def float64, description string) TaskQueueFloatSetting { setting_gen.go
352 > return NewTaskQueueTypedSettingWithConverter[float64](key, convertFloat, def, description)
353 > }
354
355 func NewTaskQueueFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) TaskQueueFloatConstrainedDefaultSetting {
366 type ShardIDFloatConstrainedDefaultSetting = ShardIDTypedConstrainedDefaultSetting[float64]
367
368 > func NewShardIDFloatSetting(key string, def float64, description string) ShardIDFloatSetting { setting_gen.go
369 > return NewShardIDTypedSettingWithConverter[float64](key, convertFloat, def, description)
370 > }
371
372 func NewShardIDFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) ShardIDFloatConstrainedDefaultSetting {
400 type DestinationFloatConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[float64]
401
402 > func NewDestinationFloatSetting(key string, def float64, description string) DestinationFloatSetting { setting_gen.go
403 > return NewDestinationTypedSettingWithConverter[float64](key, convertFloat, def, description)
404 > }
405
406 func NewDestinationFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) DestinationFloatConstrainedDefaultSetting {
434 type GlobalStringConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[string]
435
436 > func NewGlobalStringSetting(key string, def string, description string) GlobalStringSetting { setting_gen.go
437 > return NewGlobalTypedSettingWithConverter[string](key, convertString, def, description)
438 > }
439
440 func NewGlobalStringSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[string], description string) GlobalStringConstrainedDefaultSetting {
444 type StringPropertyFn = TypedPropertyFn[string]
445
446 > func GetStringPropertyFn(value string) StringPropertyFn { setting_gen.go
447 > return GetTypedPropertyFn(value)
448 > }
449
450 type NamespaceStringSetting = NamespaceTypedSetting[string]
570 type GlobalDurationConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[time.Duration]
571
572 > func NewGlobalDurationSetting(key string, def time.Duration, description string) GlobalDurationSetting { setting_gen.go
573 > return NewGlobalTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
574 > }
575
576 func NewGlobalDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) GlobalDurationConstrainedDefaultSetting {
587 type NamespaceDurationConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[time.Duration]
588
589 > func NewNamespaceDurationSetting(key string, def time.Duration, description string) NamespaceDurationSetting { setting_gen.go
590 > return NewNamespaceTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
591 > }
592
593 func NewNamespaceDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) NamespaceDurationConstrainedDefaultSetting {
604 type NamespaceIDDurationConstrainedDefaultSetting = NamespaceIDTypedConstrainedDefaultSetting[time.Duration]
605
606 > func NewNamespaceIDDurationSetting(key string, def time.Duration, description string) NamespaceIDDurationSetting { setting_gen.go
607 > return NewNamespaceIDTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
608 > }
609
610 func NewNamespaceIDDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) NamespaceIDDurationConstrainedDefaultSetting {
621 type TaskQueueDurationConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[time.Duration]
622
623 > func NewTaskQueueDurationSetting(key string, def time.Duration, description string) TaskQueueDurationSetting { setting_gen.go
624 > return NewTaskQueueTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
625 > }
626
627 > func NewTaskQueueDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) TaskQueueDurationConstrainedDefaultSetting { setting_gen.go
628 > return NewTaskQueueTypedSettingWithConstrainedDefault[time.Duration](key, convertDuration, cdef, description)
629 > }
630
631 type DurationPropertyFnWithTaskQueueFilter = TypedPropertyFnWithTaskQueueFilter[time.Duration]
638 type ShardIDDurationConstrainedDefaultSetting = ShardIDTypedConstrainedDefaultSetting[time.Duration]
639
640 > func NewShardIDDurationSetting(key string, def time.Duration, description string) ShardIDDurationSetting { setting_gen.go
641 > return NewShardIDTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
642 > }
643
644 func NewShardIDDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) ShardIDDurationConstrainedDefaultSetting {
655 type TaskTypeDurationConstrainedDefaultSetting = TaskTypeTypedConstrainedDefaultSetting[time.Duration]
656
657 > func NewTaskTypeDurationSetting(key string, def time.Duration, description string) TaskTypeDurationSetting { setting_gen.go
658 > return NewTaskTypeTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
659 > }
660
661 func NewTaskTypeDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) TaskTypeDurationConstrainedDefaultSetting {
672 type DestinationDurationConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[time.Duration]
673
674 > func NewDestinationDurationSetting(key string, def time.Duration, description string) DestinationDurationSetting { setting_gen.go
675 > return NewDestinationTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
676 > }
677
678 func NewDestinationDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) DestinationDurationConstrainedDefaultSetting {
689 type ChasmTaskTypeDurationConstrainedDefaultSetting = ChasmTaskTypeTypedConstrainedDefaultSetting[time.Duration]
690
691 > func NewChasmTaskTypeDurationSetting(key string, def time.Duration, description string) ChasmTaskTypeDurationSetting { setting_gen.go
692 > return NewChasmTaskTypeTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
693 > }
694
695 func NewChasmTaskTypeDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) ChasmTaskTypeDurationConstrainedDefaultSetting {
723 type NamespaceMapConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[map[string]any]
724
725 > func NewNamespaceMapSetting(key string, def map[string]any, description string) NamespaceMapSetting { setting_gen.go
726 > return NewNamespaceTypedSettingWithConverter[map[string]any](key, convertMap, def, description)
727 > }
728
729 func NewNamespaceMapSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[map[string]any], description string) NamespaceMapConstrainedDefaultSetting {
845 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
846 // when using non-empty maps or slices as defaults, the result may not be what you want.
847 > func NewGlobalTypedSetting[T any](key string, def T, description string) GlobalTypedSetting[T] { setting_gen.go
848 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
849 > warnDefaultSharedStructure(key, def)
850 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
851 > _ = deepCopyForMapstructure(def)
852 >
853 > s := GlobalTypedSetting[T]{
854 > key: MakeKey(key),
855 > def: def,
856 > convert: ConvertStructure[T](def),
857 > description: description,
858 > }
859 > register(s)
860 > return s
861 > }
862
863 // NewGlobalTypedSettingWithConverter creates a setting with a custom converter function.
864 > func NewGlobalTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) GlobalTypedSetting[T] { setting_gen.go
865 > s := GlobalTypedSetting[T]{
866 > key: MakeKey(key),
867 > def: def,
868 > convert: convert,
869 > description: description,
870 > }
871 > register(s)
872 > return s
873 > }
874
875 // NewGlobalTypedSettingWithConstrainedDefault creates a setting with a compound default value.
885 }
886
887 > func (s GlobalTypedSetting[T]) Key() Key { return s.key } setting_gen.go
888 func (s GlobalTypedSetting[T]) Precedence() Precedence { return PrecedenceGlobal }
889 func (s GlobalTypedSetting[T]) Validate(v any) error {
899 }
900
901 > func (s GlobalTypedSetting[T]) WithDefault(v T) GlobalTypedSetting[T] { setting_gen.go
902 > newS := s
903 > newS.def = v
904 > return newS
905 > }
906
907 type TypedPropertyFn[T any] func() T
908
909 > func (s GlobalTypedSetting[T]) Get(c *Collection) TypedPropertyFn[T] { setting_gen.go
910 > return func() T {
911 > prec := []Constraints{{}} setting_gen.go
912 > return matchAndConvert(
913 > c,
914 > s.key,
915 > s.def,
916 > s.convert,
917 > prec,
918 > )
919 > }
920 }
921
935 type TypedSubscribable[T any] func(callback func(T)) (v T, cancel func())
936
937 > func (s GlobalTypedSetting[T]) Subscribe(c *Collection) TypedSubscribable[T] { setting_gen.go
938 > return func(callback func(T)) (T, func()) {
939 > prec := []Constraints{{}} setting_gen.go
940 > return subscribe(c, s.key, s.def, s.convert, prec, callback)
941 > }
942 }
943
969 }
970
971 > func GetTypedPropertyFn[T any](value T) TypedPropertyFn[T] { setting_gen.go
972 > return func() T {
973 return value
974 }
981 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
982 // when using non-empty maps or slices as defaults, the result may not be what you want.
983 > func NewNamespaceTypedSetting[T any](key string, def T, description string) NamespaceTypedSetting[T] { setting_gen.go
984 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
985 > warnDefaultSharedStructure(key, def)
986 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
987 > _ = deepCopyForMapstructure(def)
988 >
989 > s := NamespaceTypedSetting[T]{
990 > key: MakeKey(key),
991 > def: def,
992 > convert: ConvertStructure[T](def),
993 > description: description,
994 > }
995 > register(s)
996 > return s
997 > }
998
999 // NewNamespaceTypedSettingWithConverter creates a setting with a custom converter function.
1000 > func NewNamespaceTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) NamespaceTypedSetting[T] { setting_gen.go
1001 > s := NamespaceTypedSetting[T]{
1002 > key: MakeKey(key),
1003 > def: def,
1004 > convert: convert,
1005 > description: description,
1006 > }
1007 > register(s)
1008 > return s
1009 > }
1010
1011 // NewNamespaceTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1021 }
1022
1023 > func (s NamespaceTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1024 func (s NamespaceTypedSetting[T]) Precedence() Precedence { return PrecedenceNamespace }
1025 func (s NamespaceTypedSetting[T]) Validate(v any) error {
1035 }
1036
1037 > func (s NamespaceTypedSetting[T]) WithDefault(v T) NamespaceTypedSetting[T] { setting_gen.go
1038 > newS := s
1039 > newS.def = v
1040 > return newS
1041 > }
1042
1043 type TypedPropertyFnWithNamespaceFilter[T any] func(namespace string) T
1044
1045 > func (s NamespaceTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithNamespaceFilter[T] { setting_gen.go
1046 > return func(namespace string) T {
1047 > prec := []Constraints{{Namespace: namespace}, {}} setting_gen.go
1048 > return matchAndConvert(
1049 > c,
1050 > s.key,
1051 > s.def,
1052 > s.convert,
1053 > prec,
1054 > )
1055 > }
1056 }
1057
1071 type TypedSubscribableWithNamespaceFilter[T any] func(namespace string, callback func(T)) (v T, cancel func())
1072
1073 > func (s NamespaceTypedSetting[T]) Subscribe(c *Collection) TypedSubscribableWithNamespaceFilter[T] { setting_gen.go
1074 > return func(namespace string, callback func(T)) (T, func()) {
1075 > prec := []Constraints{{Namespace: namespace}, {}} setting_gen.go
1076 > return subscribe(c, s.key, s.def, s.convert, prec, callback)
1077 > }
1078 }
1079
1105 }
1106
1107 > func GetTypedPropertyFnFilteredByNamespace[T any](value T) TypedPropertyFnWithNamespaceFilter[T] { setting_gen.go
1108 > return func(namespace string) T {
1109 return value
1110 }
1134
1135 // NewNamespaceIDTypedSettingWithConverter creates a setting with a custom converter function.
1136 > func NewNamespaceIDTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) NamespaceIDTypedSetting[T] { setting_gen.go
1137 > s := NamespaceIDTypedSetting[T]{
1138 > key: MakeKey(key),
1139 > def: def,
1140 > convert: convert,
1141 > description: description,
1142 > }
1143 > register(s)
1144 > return s
1145 > }
1146
1147 // NewNamespaceIDTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1157 }
1158
1159 > func (s NamespaceIDTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1160 func (s NamespaceIDTypedSetting[T]) Precedence() Precedence { return PrecedenceNamespaceID }
1161 func (s NamespaceIDTypedSetting[T]) Validate(v any) error {
1179 type TypedPropertyFnWithNamespaceIDFilter[T any] func(namespaceID namespace.ID) T
1180
1181 > func (s NamespaceIDTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithNamespaceIDFilter[T] { setting_gen.go
1182 > return func(namespaceID namespace.ID) T {
1183 prec := []Constraints{{NamespaceID: namespaceID.String()}, {}}
1184 return matchAndConvert(
1253 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
1254 // when using non-empty maps or slices as defaults, the result may not be what you want.
1255 > func NewTaskQueueTypedSetting[T any](key string, def T, description string) TaskQueueTypedSetting[T] { setting_gen.go
1256 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
1257 > warnDefaultSharedStructure(key, def)
1258 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
1259 > _ = deepCopyForMapstructure(def)
1260 >
1261 > s := TaskQueueTypedSetting[T]{
1262 > key: MakeKey(key),
1263 > def: def,
1264 > convert: ConvertStructure[T](def),
1265 > description: description,
1266 > }
1267 > register(s)
1268 > return s
1269 > }
1270
1271 // NewTaskQueueTypedSettingWithConverter creates a setting with a custom converter function.
1272 > func NewTaskQueueTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) TaskQueueTypedSetting[T] { setting_gen.go
1273 > s := TaskQueueTypedSetting[T]{
1274 > key: MakeKey(key),
1275 > def: def,
1276 > convert: convert,
1277 > description: description,
1278 > }
1279 > register(s)
1280 > return s
1281 > }
1282
1283 // NewTaskQueueTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1284 > func NewTaskQueueTypedSettingWithConstrainedDefault[T any](key string, convert func(any) (T, error), cdef []TypedConstrainedValue[T], description string) TaskQueueTypedConstrainedDefaultSetting[T] { setting_gen.go
1285 > s := TaskQueueTypedConstrainedDefaultSetting[T]{
1286 > key: MakeKey(key),
1287 > cdef: cdef,
1288 > convert: convert,
1289 > description: description,
1290 > }
1291 > register(s)
1292 > return s
1293 > }
1294
1295 > func (s TaskQueueTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1296 func (s TaskQueueTypedSetting[T]) Precedence() Precedence { return PrecedenceTaskQueue }
1297 func (s TaskQueueTypedSetting[T]) Validate(v any) error {
1300 }
1301
1302 > func (s TaskQueueTypedConstrainedDefaultSetting[T]) Key() Key { return s.key } setting_gen.go
1303 func (s TaskQueueTypedConstrainedDefaultSetting[T]) Precedence() Precedence { return PrecedenceTaskQueue }
1304 func (s TaskQueueTypedConstrainedDefaultSetting[T]) Validate(v any) error {
1315 type TypedPropertyFnWithTaskQueueFilter[T any] func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType) T
1316
1317 > func (s TaskQueueTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithTaskQueueFilter[T] { setting_gen.go
1318 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType) T {
1319 prec := []Constraints{
1320 {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1334 }
1335
1336 > func (s TaskQueueTypedConstrainedDefaultSetting[T]) Get(c *Collection) TypedPropertyFnWithTaskQueueFilter[T] { setting_gen.go
1337 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType) T {
1338 prec := []Constraints{
1339 {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1355 type TypedSubscribableWithTaskQueueFilter[T any] func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType, callback func(T)) (v T, cancel func())
1356
1357 > func (s TaskQueueTypedSetting[T]) Subscribe(c *Collection) TypedSubscribableWithTaskQueueFilter[T] { setting_gen.go
1358 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType, callback func(T)) (T, func()) {
1359 prec := []Constraints{
1360 {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1378 }
1379
1380 > func (s TaskQueueTypedConstrainedDefaultSetting[T]) Subscribe(c *Collection) TypedSubscribableWithTaskQueueFilter[T] { setting_gen.go
1381 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType, callback func(T)) (T, func()) {
1382 prec := []Constraints{
1383 {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1430
1431 // NewShardIDTypedSettingWithConverter creates a setting with a custom converter function.
1432 > func NewShardIDTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) ShardIDTypedSetting[T] { setting_gen.go
1433 > s := ShardIDTypedSetting[T]{
1434 > key: MakeKey(key),
1435 > def: def,
1436 > convert: convert,
1437 > description: description,
1438 > }
1439 > register(s)
1440 > return s
1441 > }
1442
1443 // NewShardIDTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1453 }
1454
1455 > func (s ShardIDTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1456 func (s ShardIDTypedSetting[T]) Precedence() Precedence { return PrecedenceShardID }
1457 func (s ShardIDTypedSetting[T]) Validate(v any) error {
1475 type TypedPropertyFnWithShardIDFilter[T any] func(shardID int32) T
1476
1477 > func (s ShardIDTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithShardIDFilter[T] { setting_gen.go
1478 > return func(shardID int32) T {
1479 > prec := []Constraints{{ShardID: shardID}, {}} setting_gen.go
1480 > return matchAndConvert(
1481 > c,
1482 > s.key,
1483 > s.def,
1484 > s.convert,
1485 > prec,
1486 > )
1487 > }
1488 }
1489
1566
1567 // NewTaskTypeTypedSettingWithConverter creates a setting with a custom converter function.
1568 > func NewTaskTypeTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) TaskTypeTypedSetting[T] { setting_gen.go
1569 > s := TaskTypeTypedSetting[T]{
1570 > key: MakeKey(key),
1571 > def: def,
1572 > convert: convert,
1573 > description: description,
1574 > }
1575 > register(s)
1576 > return s
1577 > }
1578
1579 // NewTaskTypeTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1589 }
1590
1591 > func (s TaskTypeTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1592 func (s TaskTypeTypedSetting[T]) Precedence() Precedence { return PrecedenceTaskType }
1593 func (s TaskTypeTypedSetting[T]) Validate(v any) error {
1611 type TypedPropertyFnWithTaskTypeFilter[T any] func(taskType enumsspb.TaskType) T
1612
1613 > func (s TaskTypeTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithTaskTypeFilter[T] { setting_gen.go
1614 > return func(taskType enumsspb.TaskType) T {
1615 prec := []Constraints{{TaskType: taskType}, {}}
1616 return matchAndConvert(
1685 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
1686 // when using non-empty maps or slices as defaults, the result may not be what you want.
1687 > func NewDestinationTypedSetting[T any](key string, def T, description string) DestinationTypedSetting[T] { setting_gen.go
1688 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
1689 > warnDefaultSharedStructure(key, def)
1690 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
1691 > _ = deepCopyForMapstructure(def)
1692 >
1693 > s := DestinationTypedSetting[T]{
1694 > key: MakeKey(key),
1695 > def: def,
1696 > convert: ConvertStructure[T](def),
1697 > description: description,
1698 > }
1699 > register(s)
1700 > return s
1701 > }
1702
1703 // NewDestinationTypedSettingWithConverter creates a setting with a custom converter function.
1704 > func NewDestinationTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) DestinationTypedSetting[T] { setting_gen.go
1705 > s := DestinationTypedSetting[T]{
1706 > key: MakeKey(key),
1707 > def: def,
1708 > convert: convert,
1709 > description: description,
1710 > }
1711 > register(s)
1712 > return s
1713 > }
1714
1715 // NewDestinationTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1725 }
1726
1727 > func (s DestinationTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1728 func (s DestinationTypedSetting[T]) Precedence() Precedence { return PrecedenceDestination }
1729 func (s DestinationTypedSetting[T]) Validate(v any) error {
1747 type TypedPropertyFnWithDestinationFilter[T any] func(namespace string, destination string) T
1748
1749 > func (s DestinationTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithDestinationFilter[T] { setting_gen.go
1750 > return func(namespace string, destination string) T {
1751 prec := []Constraints{
1752 {Namespace: namespace, Destination: destination},
1785 type TypedSubscribableWithDestinationFilter[T any] func(namespace string, destination string, callback func(T)) (v T, cancel func())
1786
1787 > func (s DestinationTypedSetting[T]) Subscribe(c *Collection) TypedSubscribableWithDestinationFilter[T] { setting_gen.go
1788 > return func(namespace string, destination string, callback func(T)) (T, func()) {
1789 prec := []Constraints{
1790 {Namespace: namespace, Destination: destination},
1858
1859 // NewChasmTaskTypeTypedSettingWithConverter creates a setting with a custom converter function.
1860 > func NewChasmTaskTypeTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) ChasmTaskTypeTypedSetting[T] { setting_gen.go
1861 > s := ChasmTaskTypeTypedSetting[T]{
1862 > key: MakeKey(key),
1863 > def: def,
1864 > convert: convert,
1865 > description: description,
1866 > }
1867 > register(s)
1868 > return s
1869 > }
1870
1871 // NewChasmTaskTypeTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1881 }
1882
1883 > func (s ChasmTaskTypeTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1884 func (s ChasmTaskTypeTypedSetting[T]) Precedence() Precedence { return PrecedenceChasmTaskType }
1885 func (s ChasmTaskTypeTypedSetting[T]) Validate(v any) error {
1903 type TypedPropertyFnWithChasmTaskTypeFilter[T any] func(chasmTaskType string) T
1904
1905 > func (s ChasmTaskTypeTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithChasmTaskTypeFilter[T] { setting_gen.go
1906 > return func(chasmTaskType string) T {
1907 prec := []Constraints{{ChasmTaskType: chasmTaskType}, {}}
1908 return matchAndConvert(
go.temporal.io/server/common/persistence/persistence_metric_clients.go 279 covered LOC · 41 ranges

Open complete file

77
78 // NewShardPersistenceMetricsClient creates a client to manage shards
79 > func NewShardPersistenceMetricsClient(persistence ShardManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) ShardManager { persistence_metric_clients.go
80 > return &shardPersistenceClient{
81 > metricEmitter: metricEmitter{
82 > metricsHandler: metricsHandler,
83 > logger: logger,
84 > enableDataLossMetrics: enableDataLossMetrics,
85 > },
86 > healthSignals: healthSignals,
87 > persistence: persistence,
88 > }
89 > }
90
91 // NewExecutionPersistenceMetricsClient creates a client to manage executions
92 > func NewExecutionPersistenceMetricsClient(persistence ExecutionManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) ExecutionManager { persistence_metric_clients.go
93 > return &executionPersistenceClient{
94 > metricEmitter: metricEmitter{
95 > metricsHandler: metricsHandler,
96 > logger: logger,
97 > enableDataLossMetrics: enableDataLossMetrics,
98 > },
99 > healthSignals: healthSignals,
100 > persistence: persistence,
101 > }
102 > }
103
104 // NewTaskPersistenceMetricsClient creates a client to manage tasks
105 > func NewTaskPersistenceMetricsClient(persistence TaskManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) TaskManager { persistence_metric_clients.go
106 > return &taskPersistenceClient{
107 > metricEmitter: metricEmitter{
108 > metricsHandler: metricsHandler,
109 > logger: logger,
110 > enableDataLossMetrics: enableDataLossMetrics,
111 > },
112 > healthSignals: healthSignals,
113 > persistence: persistence,
114 > }
115 > }
116
117 // NewMetadataPersistenceMetricsClient creates a MetadataManager client to manage metadata
118 > func NewMetadataPersistenceMetricsClient(persistence MetadataManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) MetadataManager { persistence_metric_clients.go
119 > return &metadataPersistenceClient{
120 > metricEmitter: metricEmitter{
121 > metricsHandler: metricsHandler,
122 > logger: logger,
123 > enableDataLossMetrics: enableDataLossMetrics,
124 > },
125 > healthSignals: healthSignals,
126 > persistence: persistence,
127 > }
128 > }
129
130 // NewClusterMetadataPersistenceMetricsClient creates a ClusterMetadataManager client to manage cluster metadata
131 > func NewClusterMetadataPersistenceMetricsClient(persistence ClusterMetadataManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) ClusterMetadataManager { persistence_metric_clients.go
132 > return &clusterMetadataPersistenceClient{
133 > metricEmitter: metricEmitter{
134 > metricsHandler: metricsHandler,
135 > logger: logger,
136 > enableDataLossMetrics: enableDataLossMetrics,
137 > },
138 > healthSignals: healthSignals,
139 > persistence: persistence,
140 > }
141 > }
142
143 // NewQueuePersistenceMetricsClient creates a client to manage queue
144 > func NewQueuePersistenceMetricsClient(persistence Queue, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) Queue { persistence_metric_clients.go
145 > return &queuePersistenceClient{
146 > metricEmitter: metricEmitter{
147 > metricsHandler: metricsHandler,
148 > logger: logger,
149 > enableDataLossMetrics: enableDataLossMetrics,
150 > },
151 > healthSignals: healthSignals,
152 > persistence: persistence,
153 > }
154 > }
155
156 // NewNexusEndpointPersistenceMetricsClient creates a NexusEndpointManager to manage nexus endpoints
157 > func NewNexusEndpointPersistenceMetricsClient(persistence NexusEndpointManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) NexusEndpointManager { persistence_metric_clients.go
158 > return &nexusEndpointPersistenceClient{
159 > metricEmitter: metricEmitter{
160 > metricsHandler: metricsHandler,
161 > logger: logger,
162 > enableDataLossMetrics: enableDataLossMetrics,
163 > },
164 > healthSignals: healthSignals,
165 > persistence: persistence,
166 > }
167 > }
168
169 func (p *shardPersistenceClient) GetName() string {
174 ctx context.Context,
175 request *GetOrCreateShardRequest,
176 > ) (_ *GetOrCreateShardResponse, retErr error) { persistence_metric_clients.go
177 > caller := headers.GetCallerInfo(ctx).CallerName
178 > startTime := time.Now().UTC()
179 > defer func() {
180 > latency := time.Since(startTime)
181 > p.healthSignals.Record(request.ShardID, latency, retErr)
182 > p.recordRequestMetrics(metrics.PersistenceGetOrCreateShardScope, caller, latency, retErr)
183 > p.recordDataLossMetrics(metrics.PersistenceGetOrCreateShardScope, caller, retErr, "", "")
184 > }()
185 > return p.persistence.GetOrCreateShard(ctx, request)
186 }
187
189 ctx context.Context,
190 request *UpdateShardRequest,
191 > ) (retErr error) { persistence_metric_clients.go
192 > caller := headers.GetCallerInfo(ctx).CallerName
193 > startTime := time.Now().UTC()
194 > defer func() {
195 > p.healthSignals.Record(request.ShardInfo.GetShardId(), time.Since(startTime), retErr)
196 > p.recordRequestMetrics(metrics.PersistenceUpdateShardScope, caller, time.Since(startTime), retErr)
197 > p.recordDataLossMetrics(metrics.PersistenceUpdateShardScope, caller, retErr, "", "")
198 > }()
199 > return p.persistence.UpdateShard(ctx, request)
200 }
201
203 ctx context.Context,
204 request *AssertShardOwnershipRequest,
205 > ) (retErr error) { persistence_metric_clients.go
206 > caller := headers.GetCallerInfo(ctx).CallerName
207 > startTime := time.Now().UTC()
208 > defer func() {
209 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
210 > p.recordRequestMetrics(metrics.PersistenceAssertShardOwnershipScope, caller, time.Since(startTime), retErr)
211 > p.recordDataLossMetrics(metrics.PersistenceAssertShardOwnershipScope, caller, retErr, "", "")
212 > }()
213 > return p.persistence.AssertShardOwnership(ctx, request)
214 }
215
216 > func (p *shardPersistenceClient) Close() { persistence_metric_clients.go
217 > p.persistence.Close()
218 > }
219
220 > func (p *executionPersistenceClient) GetName() string { persistence_metric_clients.go
221 > return p.persistence.GetName()
222 > }
223
224 func (p *executionPersistenceClient) GetHistoryBranchUtil() HistoryBranchUtil {
419 ctx context.Context,
420 request *GetHistoryTasksRequest,
421 > ) (_ *GetHistoryTasksResponse, retErr error) { persistence_metric_clients.go
422 > var operation string
423 > switch request.TaskCategory.ID() {
424 > case tasks.CategoryIDTransfer:
425 > operation = metrics.PersistenceGetTransferTasksScope
426 > case tasks.CategoryIDTimer:
427 > operation = metrics.PersistenceGetTimerTasksScope
428 > case tasks.CategoryIDVisibility:
429 > operation = metrics.PersistenceGetVisibilityTasksScope
430 case tasks.CategoryIDReplication:
431 operation = metrics.PersistenceGetReplicationTasksScope
432 case tasks.CategoryIDArchival:
433 operation = metrics.PersistenceGetArchivalTasksScope
434 > case tasks.CategoryIDOutbound: persistence_metric_clients.go
435 > operation = metrics.PersistenceGetOutboundTasksScope
436 default:
437 return nil, serviceerror.NewInternalf("unknown task category type: %v", request.TaskCategory)
438 }
439
440 > caller := headers.GetCallerInfo(ctx).CallerName persistence_metric_clients.go
441 > startTime := time.Now().UTC()
442 > defer func() {
443 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
444 > p.recordRequestMetrics(operation, caller, time.Since(startTime), retErr)
445 > p.recordDataLossMetrics(operation, caller, retErr, "", "")
446 > }()
447 > return p.persistence.GetHistoryTasks(ctx, request)
448 }
449
587 }
588
589 > func (p *executionPersistenceClient) Close() { persistence_metric_clients.go
590 > p.persistence.Close()
591 > }
592
593 func (p *taskPersistenceClient) GetName() string {
771 }
772
773 > func (p *taskPersistenceClient) Close() { persistence_metric_clients.go
774 > p.persistence.Close()
775 > }
776
777 func (p *metadataPersistenceClient) GetName() string {
796 ctx context.Context,
797 request *GetNamespaceRequest,
798 > ) (_ *GetNamespaceResponse, retErr error) { persistence_metric_clients.go
799 > caller := headers.GetCallerInfo(ctx).CallerName
800 > startTime := time.Now().UTC()
801 > defer func() {
802 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
803 > p.recordRequestMetrics(metrics.PersistenceGetNamespaceScope, caller, time.Since(startTime), retErr)
804 > p.recordDataLossMetrics(metrics.PersistenceGetNamespaceScope, caller, retErr, "", "")
805 > }()
806 > return p.persistence.GetNamespace(ctx, request)
807 }
808
866 ctx context.Context,
867 request *ListNamespacesRequest,
868 > ) (_ *ListNamespacesResponse, retErr error) { persistence_metric_clients.go
869 > caller := headers.GetCallerInfo(ctx).CallerName
870 > startTime := time.Now().UTC()
871 > defer func() {
872 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
873 > p.recordRequestMetrics(metrics.PersistenceListNamespacesScope, caller, time.Since(startTime), retErr)
874 > p.recordDataLossMetrics(metrics.PersistenceListNamespacesScope, caller, retErr, "", "")
875 > }()
876 > return p.persistence.ListNamespaces(ctx, request)
877 }
878
890 }
891
892 > func (p *metadataPersistenceClient) WatchNamespaces(ctx context.Context) (_ <-chan *NamespaceWatchEvent, retErr error) { persistence_metric_clients.go
893 > caller := headers.GetCallerInfo(ctx).CallerName
894 > startTime := time.Now().UTC()
895 > defer func() {
896 > metricErr := retErr
897 > // WatchNotSupported isn't really a persistence error. It's just a signal that persistence doesn't support watching.
898 > if errors.Is(metricErr, ErrWatchNotSupported) {
899 > metricErr = nil
900 > }
901 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), metricErr)
902 > p.recordRequestMetrics(metrics.PersistenceWatchNamespacesScope, caller, time.Since(startTime), metricErr)
903 > p.recordDataLossMetrics(metrics.PersistenceWatchNamespacesScope, caller, metricErr, "", "")
904 }()
905 > return p.persistence.WatchNamespaces(ctx) persistence_metric_clients.go
906 }
907
908 > func (p *metadataPersistenceClient) Close() { persistence_metric_clients.go
909 > p.persistence.Close()
910 > }
911
912 // AppendHistoryNodes add a node to history node table
1055 ctx context.Context,
1056 blob *commonpb.DataBlob,
1058 > return p.persistence.Init(ctx, blob)
1059 > }
1060
1061 func (p *queuePersistenceClient) EnqueueMessage(
1216 }
1217
1218 > func (p *queuePersistenceClient) Close() { persistence_metric_clients.go
1219 > p.persistence.Close()
1220 > }
1221
1222 > func (p *clusterMetadataPersistenceClient) Close() { persistence_metric_clients.go
1223 > p.persistence.Close()
1224 > }
1225
1226 func (p *clusterMetadataPersistenceClient) ListClusterMetadata(
1227 ctx context.Context,
1228 request *ListClusterMetadataRequest,
1229 > ) (_ *ListClusterMetadataResponse, retErr error) { persistence_metric_clients.go
1230 > caller := headers.GetCallerInfo(ctx).CallerName
1231 > startTime := time.Now().UTC()
1232 > defer func() {
1233 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1234 > p.recordRequestMetrics(metrics.PersistenceListClusterMetadataScope, caller, time.Since(startTime), retErr)
1235 > p.recordDataLossMetrics(metrics.PersistenceListClusterMetadataScope, caller, retErr, "", "")
1236 > }()
1237 > return p.persistence.ListClusterMetadata(ctx, request)
1238 }
1239
1240 func (p *clusterMetadataPersistenceClient) GetCurrentClusterMetadata(
1241 ctx context.Context,
1242 > ) (_ *GetClusterMetadataResponse, retErr error) { persistence_metric_clients.go
1243 > caller := headers.GetCallerInfo(ctx).CallerName
1244 > startTime := time.Now().UTC()
1245 > defer func() {
1246 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1247 > p.recordRequestMetrics(metrics.PersistenceGetCurrentClusterMetadataScope, caller, time.Since(startTime), retErr)
1248 > p.recordDataLossMetrics(metrics.PersistenceGetCurrentClusterMetadataScope, caller, retErr, "", "")
1249 > }()
1250 > return p.persistence.GetCurrentClusterMetadata(ctx)
1251 }
1252
1254 ctx context.Context,
1255 request *GetClusterMetadataRequest,
1256 > ) (_ *GetClusterMetadataResponse, retErr error) { persistence_metric_clients.go
1257 > caller := headers.GetCallerInfo(ctx).CallerName
1258 > startTime := time.Now().UTC()
1259 > defer func() {
1260 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1261 > p.recordRequestMetrics(metrics.PersistenceGetClusterMetadataScope, caller, time.Since(startTime), retErr)
1262 > p.recordDataLossMetrics(metrics.PersistenceGetClusterMetadataScope, caller, retErr, "", "")
1263 > }()
1264 > return p.persistence.GetClusterMetadata(ctx, request)
1265 }
1266
1268 ctx context.Context,
1269 request *SaveClusterMetadataRequest,
1270 > ) (_ bool, retErr error) { persistence_metric_clients.go
1271 > caller := headers.GetCallerInfo(ctx).CallerName
1272 > startTime := time.Now().UTC()
1273 > defer func() {
1274 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1275 > p.recordRequestMetrics(metrics.PersistenceSaveClusterMetadataScope, caller, time.Since(startTime), retErr)
1276 > p.recordDataLossMetrics(metrics.PersistenceSaveClusterMetadataScope, caller, retErr, "", "")
1277 > }()
1278 > return p.persistence.SaveClusterMetadata(ctx, request)
1279 }
1280
1300 ctx context.Context,
1301 request *GetClusterMembersRequest,
1302 > ) (_ *GetClusterMembersResponse, retErr error) { persistence_metric_clients.go
1303 > caller := headers.GetCallerInfo(ctx).CallerName
1304 > startTime := time.Now().UTC()
1305 > defer func() {
1306 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1307 > p.recordRequestMetrics(metrics.PersistenceGetClusterMembersScope, caller, time.Since(startTime), retErr)
1308 > p.recordDataLossMetrics(metrics.PersistenceGetClusterMembersScope, caller, retErr, "", "")
1309 > }()
1310 > return p.persistence.GetClusterMembers(ctx, request)
1311 }
1312
1314 ctx context.Context,
1315 request *UpsertClusterMembershipRequest,
1316 > ) (retErr error) { persistence_metric_clients.go
1317 > caller := headers.GetCallerInfo(ctx).CallerName
1318 > startTime := time.Now().UTC()
1319 > defer func() {
1320 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1321 > p.recordRequestMetrics(metrics.PersistenceUpsertClusterMembershipScope, caller, time.Since(startTime), retErr)
1322 > p.recordDataLossMetrics(metrics.PersistenceUpsertClusterMembershipScope, caller, retErr, "", "")
1323 > }()
1324 > return p.persistence.UpsertClusterMembership(ctx, request)
1325 }
1326
1328 ctx context.Context,
1329 request *PruneClusterMembershipRequest,
1330 > ) (retErr error) { persistence_metric_clients.go
1331 > caller := headers.GetCallerInfo(ctx).CallerName
1332 > startTime := time.Now().UTC()
1333 > defer func() {
1334 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1335 > p.recordRequestMetrics(metrics.PersistencePruneClusterMembershipScope, caller, time.Since(startTime), retErr)
1336 > p.recordDataLossMetrics(metrics.PersistencePruneClusterMembershipScope, caller, retErr, "", "")
1337 > }()
1338 > return p.persistence.PruneClusterMembership(ctx, request)
1339 }
1340
1342 ctx context.Context,
1343 currentClusterName string,
1344 > ) (retErr error) { persistence_metric_clients.go
1345 > caller := headers.GetCallerInfo(ctx).CallerName
1346 > startTime := time.Now().UTC()
1347 > defer func() {
1348 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1349 > p.recordRequestMetrics(metrics.PersistenceInitializeSystemNamespaceScope, caller, time.Since(startTime), retErr)
1350 > p.recordDataLossMetrics(metrics.PersistenceInitializeSystemNamespaceScope, caller, retErr, "", "")
1351 > }()
1352 > return p.persistence.InitializeSystemNamespaces(ctx, currentClusterName)
1353 }
1354
1357 }
1358
1359 > func (p *nexusEndpointPersistenceClient) Close() { persistence_metric_clients.go
1360 > p.persistence.Close()
1361 > }
1362
1363 func (p *nexusEndpointPersistenceClient) GetNexusEndpoint(
1378 ctx context.Context,
1379 request *ListNexusEndpointsRequest,
1380 > ) (_ *ListNexusEndpointsResponse, retErr error) { persistence_metric_clients.go
1381 > caller := headers.GetCallerInfo(ctx).CallerName
1382 > startTime := time.Now().UTC()
1383 > defer func() {
1384 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1385 > p.recordRequestMetrics(metrics.PersistenceListNexusEndpointsScope, caller, time.Since(startTime), retErr)
1386 > p.recordDataLossMetrics(metrics.PersistenceListNexusEndpointsScope, caller, retErr, "", "")
1387 > }()
1388 > return p.persistence.ListNexusEndpoints(ctx, request)
1389 }
1390
1417 }
1418
1419 > func (p *metricEmitter) recordRequestMetrics(operation string, caller string, latency time.Duration, err error) { persistence_metric_clients.go
1420 > handler := p.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.NamespaceTag(caller))
1421 > metrics.PersistenceRequests.With(handler).Record(1)
1422 > metrics.PersistenceLatency.With(handler).Record(latency)
1423 > updateErrorMetric(handler, p.logger, operation, err)
1424 > }
1425
1426 > func (p *metricEmitter) recordDataLossMetrics(operation string, caller string, err error, workflowID, runID string) { persistence_metric_clients.go
1427 > // Emit data loss metrics if enabled and error is DataLoss
1428 > var dataLoss *serviceerror.DataLoss
1429 > if errors.As(err, &dataLoss) {
1430 if p.enableDataLossMetrics() {
1431 EmitDataLossMetric(p.metricsHandler, caller, workflowID, runID, operation, err)
1434 }
1435
1436 > func updateErrorMetric(handler metrics.Handler, logger log.Logger, operation string, err error) { persistence_metric_clients.go
1437 > if err != nil {
1438 > metrics.PersistenceErrorWithType.With(handler).Record(1, metrics.ServiceErrorTypeTag(err)) persistence_metric_clients.go
1439 > if common.IsContextCanceledErr(err) {
1440 // no-op
1441 return
1442 }
1443 > switch err := err.(type) { persistence_metric_clients.go
1444 case *ShardAlreadyExistError,
1445 *ShardOwnershipLostError,
1452 *serviceerror.NamespaceAlreadyExists,
1453 *serviceerror.NotFound,
1454 > *serviceerror.NamespaceNotFound: persistence_metric_clients.go
1455 // no-op
1456
go.temporal.io/server/service/worker/pernamespaceworker.go 262 covered LOC · 59 ranges

Open complete file

112 components []workercommon.PerNSWorkerComponent,
113 taskQueueName string,
114 > ) *PerNamespaceWorkerManager { pernamespaceworker.go
115 > return &PerNamespaceWorkerManager{
116 > logger: log.With(logger, tag.ComponentPerNSWorkerManager),
117 > sdkClientFactory: sdkClientFactory,
118 > namespaceRegistry: namespaceRegistry,
119 > hostName: hostName,
120 > taskQueueName: taskQueueName,
121 > config: config,
122 > components: components,
123 > initialRetry: 1 * time.Second,
124 > thisClusterName: clusterMetadata.GetCurrentClusterName(),
125 > startLimiter: quotas.NewDefaultOutgoingRateLimiter(quotas.RateFn(config.PerNamespaceWorkerStartRate)),
126 > membershipChangedCh: make(chan *membership.ChangedEvent),
127 > workers: make(map[namespace.ID]*perNamespaceWorker),
128 > }
129 > }
130
131 > func (wm *PerNamespaceWorkerManager) Running() bool { pernamespaceworker.go
132 > return atomic.LoadInt32(&wm.status) == common.DaemonStatusStarted
133 > }
134
135 func (wm *PerNamespaceWorkerManager) Start(
136 self membership.HostInfo,
137 serviceResolver membership.ServiceResolver,
139 > if !atomic.CompareAndSwapInt32(
140 > &wm.status,
141 > common.DaemonStatusInitialized,
142 > common.DaemonStatusStarted,
143 > ) {
144 return
145 }
146
147 > wm.self = self pernamespaceworker.go
148 > wm.serviceResolver = serviceResolver
149 >
150 > wm.logger.Info("", tag.LifeCycleStarting)
151 >
152 > // this will call namespaceCallback with current namespaces
153 > wm.namespaceRegistry.RegisterStateChangeCallback(wm, wm.namespaceCallback)
154 >
155 > err := wm.serviceResolver.AddListener(fmt.Sprintf("%p", wm), wm.membershipChangedCh)
156 > if err != nil {
157 wm.logger.Fatal("Unable to register membership listener", tag.Error(err))
158 }
159 > wm.backgroundLoops.Go(wm.membershipChangedListener) pernamespaceworker.go
160 > wm.backgroundLoops.Go(wm.periodicRefreshLoop)
161 >
162 > wm.logger.Info("", tag.LifeCycleStarted)
163 }
164
165 > func (wm *PerNamespaceWorkerManager) Stop() { pernamespaceworker.go
166 > if !atomic.CompareAndSwapInt32(
167 > &wm.status,
168 > common.DaemonStatusStarted,
169 > common.DaemonStatusStopped,
170 > ) {
171 return
172 }
173
174 > wm.logger.Info("", tag.LifeCycleStopping) pernamespaceworker.go
175 >
176 > wm.namespaceRegistry.UnregisterStateChangeCallback(wm)
177 > err := wm.serviceResolver.RemoveListener(fmt.Sprintf("%p", wm))
178 > if err != nil {
179 wm.logger.Error("Unable to unregister membership listener", tag.Error(err))
180 }
181 > wm.backgroundLoops.Cancel() pernamespaceworker.go
182 > wm.backgroundLoops.Wait()
183 >
184 > wm.lock.Lock()
185 > workers := expmaps.Values(wm.workers)
186 > maps.DeleteFunc(wm.workers, func(_ namespace.ID, _ *perNamespaceWorker) bool { return true })
187 > wm.lock.Unlock()
188 >
189 > for _, worker := range workers {
190 > worker.stopWorkerAndResetTimer() pernamespaceworker.go
191 > worker.cancel()
192 > }
193
194 > wm.logger.Info("", tag.LifeCycleStopped) pernamespaceworker.go
195 }
196
197 > func (wm *PerNamespaceWorkerManager) namespaceCallback(ns *namespace.Namespace, nsDeleted bool) { pernamespaceworker.go
198 > go wm.getWorkerByNamespace(ns).update(ns, nsDeleted, nil, nil)
199 > }
200
201 func (wm *PerNamespaceWorkerManager) refreshAll() {
207 }
208
209 > func (wm *PerNamespaceWorkerManager) membershipChangedListener(ctx context.Context) error { pernamespaceworker.go
210 > for {
211 > select {
212 > case <-ctx.Done(): pernamespaceworker.go
213 > return nil
214 case <-wm.membershipChangedCh:
215 wm.refreshAll()
218 }
219
220 > func (wm *PerNamespaceWorkerManager) periodicRefreshLoop(ctx context.Context) error { pernamespaceworker.go
221 > ticker := time.NewTicker(refreshInterval)
222 > defer ticker.Stop()
223 >
224 > for {
225 > select {
226 > case <-ctx.Done(): pernamespaceworker.go
227 > return nil
228 case <-ticker.C:
229 wm.refreshAll()
232 }
233
234 > func (wm *PerNamespaceWorkerManager) getWorkerByNamespace(ns *namespace.Namespace) *perNamespaceWorker { pernamespaceworker.go
235 > wm.lock.Lock()
236 > defer wm.lock.Unlock()
237 >
238 > if worker, ok := wm.workers[ns.ID()]; ok {
239 return worker
240 }
241
242 > worker := &perNamespaceWorker{ pernamespaceworker.go
243 > wm: wm,
244 > logger: log.With(wm.logger, tag.WorkflowNamespace(ns.Name().String())),
245 > retrier: backoff.NewRetrier(backoff.NewExponentialRetryPolicy(wm.initialRetry), clock.NewRealTimeSource()),
246 > }
247 > count, c1 := wm.config.PerNamespaceWorkerCount(ns.Name().String(), worker.setWorkerCount)
248 > opts, c2 := wm.config.PerNamespaceWorkerOptions(ns.Name().String(), worker.setWorkerOptions)
249 > worker.ns = ns
250 > worker.count = count
251 > worker.opts = opts
252 > worker.cancel = func() { c1(); c2() }
253
254 > wm.workers[ns.ID()] = worker pernamespaceworker.go
255 > return worker
256 }
257
266 }
267
268 > func (w *perNamespaceWorker) getWorkerAllocation(args refreshArgs) (workerAllocation, error) { pernamespaceworker.go
269 > if args.count < 0 {
270 return workerAllocation{}, errInvalidConfiguration
271 > } else if args.count == 0 { pernamespaceworker.go
272 return workerAllocation{0, 0}, nil
273 }
274 > localCount, err := w.getLocallyDesiredWorkers(args) pernamespaceworker.go
275 > if err != nil {
276 return workerAllocation{}, err
277 }
278 > return workerAllocation{total: args.count, local: localCount}, nil pernamespaceworker.go
279 }
280
281 > func (w *perNamespaceWorker) getLocallyDesiredWorkers(args refreshArgs) (int, error) { pernamespaceworker.go
282 > key := args.ns.ID().String()
283 > availableHosts := w.wm.serviceResolver.LookupN(key, args.count)
284 > hostsCount := len(availableHosts)
285 > if hostsCount == 0 {
286 return 0, membership.ErrInsufficientHosts
287 }
288 > maxWorkersPerHost := args.count/hostsCount + 1 pernamespaceworker.go
289 > desiredDistribution := util.RepeatSlice(availableHosts, maxWorkersPerHost)[:args.count]
290 >
291 > isLocal := func(info membership.HostInfo) bool { return info.Identity() == w.wm.self.Identity() }
292 > result := len(util.FilterSlice(desiredDistribution, isLocal))
293 > return result, nil
294 }
295
303
304 // called on namespace state change callback, membership change, and dynamic config change
305 > func (w *perNamespaceWorker) update(ns *namespace.Namespace, nsDeleted bool, newCount *int, newOpts *sdkworker.Options) { pernamespaceworker.go
306 > w.lock.Lock()
307 >
308 > if ns != nil {
309 > w.ns = ns
310 > // The name inside of *ns, which was used to initialize the logger, can change, but
311 > // don't update w.logger here, otherwise we'd have to hold w.lock just to log.
312 > }
313 > if newCount != nil {
314 w.count = *newCount
315 }
316 > if newOpts != nil { pernamespaceworker.go
317 w.opts = *newOpts
318 }
319
320 > refreshArgs := w.refreshArgs // copy before releasing lock pernamespaceworker.go
321 > isRetrying := w.retryTimer != nil
322 > w.lock.Unlock()
323 >
324 > if nsDeleted {
325 w.stopWorkerAndResetTimer()
326 // if namespace is fully deleted from db, we can remove from our map also
329 }
330
331 > if !isRetrying { pernamespaceworker.go
332 > w.refresh(refreshArgs)
333 > }
334 }
335
336 // handleError should be called on errors from worker creation or run. it will attempt to
337 // refresh the worker again at a later time.
338 > func (w *perNamespaceWorker) handleError(err error) { pernamespaceworker.go
339 > if err == nil {
340 return
341 }
342 > if errors.Is(err, errNoWorkerNeeded) { pernamespaceworker.go
343 w.stopWorkerAndResetTimer()
344 return
345 }
346
347 > w.lock.Lock() pernamespaceworker.go
348 > defer w.lock.Unlock()
349 >
350 > if w.retryTimer != nil {
351 // this shouldn't ever happen
352 w.logger.Error("bug: handleError found existing timer")
354 }
355
356 > var sleep time.Duration pernamespaceworker.go
357 >
358 > if retryAfter, ok := err.(errRetryAfter); ok {
359 // asked for an explicit delay due to rate limit, use that
360 sleep = time.Duration(retryAfter)
361 > } else { pernamespaceworker.go
362 > sleep = w.retrier.NextBackOff(err) pernamespaceworker.go
363 > if sleep < 0 {
364 w.logger.Error("Failed to start sdk worker, out of retries", tag.Error(err))
365 return
366 }
367 > w.logger.Warn("Failed to start sdk worker", tag.Error(err), tag.Duration("sleep", sleep)) pernamespaceworker.go
368 }
369
370 > w.retryTimer = time.AfterFunc(sleep, func() { pernamespaceworker.go
371 w.lock.Lock()
372 w.retryTimer = nil
379 // Returning an error from here means that we should retry creating/starting the worker.
380 // Returning noWorkerNeeded means any existing worker should be stopped.
381 > func (w *perNamespaceWorker) refresh(args refreshArgs) (retErr error) { pernamespaceworker.go
382 > defer func() {
383 > w.handleError(retErr)
384 > }()
385
386 // note w.lock is not locked until we're about to start/stop a worker
387
388 > if !w.wm.Running() || pernamespaceworker.go
389 > args.ns.State() == enumspb.NAMESPACE_STATE_DELETED ||
390 > //nolint:forbidigo // per-namespace worker lifecycle, no workflow context
391 > !args.ns.ActiveInCluster(w.wm.thisClusterName) {
392
393 return errNoWorkerNeeded
395
396 // figure out which components are enabled at all for this namespace
397 > var enabledComponents []workercommon.PerNSWorkerComponent pernamespaceworker.go
398 > var componentSet strings.Builder
399 > for _, cmp := range w.wm.components {
400 > options := cmp.DedicatedWorkerOptions(args.ns)
401 > if options.Enabled {
402 > enabledComponents = append(enabledComponents, cmp) pernamespaceworker.go
403 > fmt.Fprintf(&componentSet, "%p,", cmp)
404 > }
405 }
406
407 > if len(enabledComponents) == 0 { pernamespaceworker.go
408 // no components enabled, we don't need a worker
409 return errNoWorkerNeeded
411
412 // check if we are responsible for this namespace at all
413 > workerAllocation, err := w.getWorkerAllocation(args) pernamespaceworker.go
414 > if err != nil {
415 w.logger.Error("Failed to look up hosts", tag.Error(err))
416 // TODO: add metric also
417 return err
418 }
419 > if workerAllocation.local == 0 { pernamespaceworker.go
420 // not ours, don't need a worker
421 return errNoWorkerNeeded
422 }
423 // ensure this changes if multiplicity changes
424 > fmt.Fprintf(&componentSet, "%d,", workerAllocation.local) pernamespaceworker.go
425 >
426 > // get sdk worker options
427 > fmt.Fprintf(&componentSet, "%+v,", w.opts)
428 >
429 > // we do need a worker, but maybe we have one already
430 > w.lock.Lock()
431 > defer w.lock.Unlock()
432 >
433 > if args.ns != w.ns {
434 // stale refresh goroutine, do nothing
435 return nil
436 }
437
438 > if componentSet.String() == w.componentSet { pernamespaceworker.go
439 // no change in set of components enabled, leave existing running
440 return nil
442
443 // ask rate limiter if we can start now
444 > if !w.reserved { pernamespaceworker.go
445 > w.reserved = true
446 > if delay := w.wm.startLimiter.Reserve().Delay(); delay > 0 {
447 return errRetryAfter(delay)
448 }
450
451 // set of components changed, need to recreate worker. first stop old one
452 > w.stopWorkerLocked() pernamespaceworker.go
453 >
454 > // create new one. note that even before startWorker returns, the worker may have started
455 > // and already called the fatal error handler. we need to set w.client+worker+componentSet
456 > // before releasing the lock to keep our state consistent.
457 > client, worker, err := w.startWorker(enabledComponents, workerAllocation)
458 > if err != nil {
459 > // TODO: add metric also pernamespaceworker.go
460 > w.stopWorkerLocked() // for calling cleanup
461 > return err
462 > }
463
464 w.client = client
471 components []workercommon.PerNSWorkerComponent,
472 allocation workerAllocation,
473 > ) (sdkclient.Client, sdkworker.Worker, error) { pernamespaceworker.go
474 > nsName := w.ns.Name().String()
475 > // this should not block because it uses an existing grpc connection
476 > client := w.wm.sdkClientFactory.NewClient(sdkclient.Options{
477 > Namespace: nsName,
478 > DataConverter: sdk.PreferProtoDataConverter,
479 > })
480 >
481 > var sdkoptions sdkworker.Options
482 >
483 > // copy from dynamic config. apply explicit defaults for some instead of using the sdk
484 > // defaults so that we can multiply below.
485 > sdkoptions.MaxConcurrentActivityExecutionSize = cmp.Or(w.opts.MaxConcurrentActivityExecutionSize, 1000)
486 > sdkoptions.WorkerActivitiesPerSecond = w.opts.WorkerActivitiesPerSecond
487 > sdkoptions.MaxConcurrentLocalActivityExecutionSize = cmp.Or(w.opts.MaxConcurrentLocalActivityExecutionSize, 1000)
488 > sdkoptions.WorkerLocalActivitiesPerSecond = w.opts.WorkerLocalActivitiesPerSecond
489 > sdkoptions.MaxConcurrentActivityTaskPollers = max(cmp.Or(w.opts.MaxConcurrentActivityTaskPollers, 2), 2)
490 > sdkoptions.MaxConcurrentWorkflowTaskExecutionSize = cmp.Or(w.opts.MaxConcurrentWorkflowTaskExecutionSize, 1000)
491 > sdkoptions.MaxConcurrentWorkflowTaskPollers = max(cmp.Or(w.opts.MaxConcurrentWorkflowTaskPollers, 2), 2)
492 > sdkoptions.StickyScheduleToStartTimeout = w.opts.StickyScheduleToStartTimeout
493 >
494 > sdkoptions.BackgroundActivityContext = headers.SetCallerInfo(context.Background(), headers.NewBackgroundHighCallerInfo(nsName))
495 > sdkoptions.Identity = fmt.Sprintf("temporal-system@%s@%s", w.wm.hostName, nsName)
496 > // increase these if we're supposed to run with more allocation
497 > sdkoptions.MaxConcurrentWorkflowTaskPollers *= allocation.local
498 > sdkoptions.MaxConcurrentActivityTaskPollers *= allocation.local
499 > sdkoptions.MaxConcurrentLocalActivityExecutionSize *= allocation.local
500 > sdkoptions.MaxConcurrentWorkflowTaskExecutionSize *= allocation.local
501 > sdkoptions.MaxConcurrentActivityExecutionSize *= allocation.local
502 > sdkoptions.OnFatalError = w.onFatalError
503 >
504 > // this should not block because the client already has server capabilities
505 > worker := w.wm.sdkClientFactory.NewWorker(client, w.wm.taskQueueName, sdkoptions)
506 > details := workercommon.RegistrationDetails{
507 > TotalWorkers: allocation.total,
508 > Multiplicity: allocation.local,
509 > }
510 > for _, cmp := range components {
511 > cleanup := cmp.Register(worker, w.ns, details)
512 > if cleanup != nil {
513 > w.cleanup = append(w.cleanup, cleanup) pernamespaceworker.go
514 > }
515 }
516
517 // this blocks by calling DescribeNamespace a few times (with a 10s timeout)
518 > err := worker.Start() pernamespaceworker.go
519 > if err != nil {
520 > client.Close() pernamespaceworker.go
521 > return nil, nil, err
522 > }
523
524 return client, worker, nil
548 }
549
550 > func (w *perNamespaceWorker) stopWorkerAndResetTimer() { pernamespaceworker.go
551 > w.lock.Lock()
552 > defer w.lock.Unlock()
553 >
554 > w.stopWorkerLocked()
555 > w.retrier.Reset()
556 > // Note that we only reset reserved here, not in stopWorkerLocked: if we did it there, we
557 > // would take a rate limiter token on each retry after failure. Failure to start the worker
558 > // means we probably didn't do any polls yet, which is the main reason for the rate limit,
559 > // so this it's okay to use only the backoff timer in that case.
560 > w.reserved = false
561 > if w.retryTimer != nil {
562 > w.retryTimer.Stop() pernamespaceworker.go
563 > w.retryTimer = nil
564 > }
565 }
566
567 > func (w *perNamespaceWorker) stopWorkerLocked() { pernamespaceworker.go
568 > for _, cleanup := range w.cleanup {
569 > cleanup() pernamespaceworker.go
570 > }
571 > w.cleanup = nil pernamespaceworker.go
572 > if w.worker != nil {
573 w.worker.Stop()
574 w.worker = nil
575 }
576 > if w.client != nil { pernamespaceworker.go
577 w.client.Close()
578 w.client = nil
579 }
580 > w.componentSet = "" pernamespaceworker.go
581 }
582
go.temporal.io/server/service/history/fx.go 261 covered LOC · 37 ranges

Open complete file

108 chasmRegistry *chasm.Registry,
109 testHooks testhooks.TestHooks,
110 > ) { fx.go
111 > if hook, ok := testhooks.Get(
112 > testHooks,
113 > testhooks.HistoryChasmRuntimeProvider,
114 > testhooks.GlobalScope,
115 > ); ok {
116 hook(chasmEngine, chasmVisibilityManager, chasmRegistry)
117 }
129 )
130
131 > func ServerProvider(grpcServerOptions []grpc.ServerOption) *grpc.Server { fx.go
132 > return grpc.NewServer(grpcServerOptions...)
133 > }
134
135 > func HistoryServiceServerProvider(handler *Handler) historyservice.HistoryServiceServer { fx.go
136 > return handler
137 > }
138
139 func ServiceResolverProvider(
140 membershipMonitor membership.Monitor,
141 > ) (membership.ServiceResolver, error) { fx.go
142 > return membershipMonitor.GetResolver(primitives.HistoryService)
143 > }
144
145 > func HandlerProvider(args NewHandlerArgs, lc fx.Lifecycle) (*Handler, error) { fx.go
146 > handler := &Handler{
147 > status: common.DaemonStatusInitialized,
148 > config: args.Config,
149 > nexusCompletionHandler: args.NexusCompletionHandler,
150 > tokenSerializer: tasktoken.NewSerializer(),
151 > deepHealthCheckHandler: deepHealthCheckHandler{
152 > healthServer: args.HealthServer,
153 > metricsHandler: args.MetricsHandler,
154 > config: args.Config,
155 > historyHealthSignal: args.HistoryHealthSignal,
156 > persistenceHealthSignal: args.PersistenceHealthSignal,
157 > startupTime: time.Now(),
158 > },
159 > logger: args.Logger,
160 > throttledLogger: args.ThrottledLogger,
161 > persistenceExecutionManager: args.PersistenceExecutionManager,
162 > persistenceShardManager: args.PersistenceShardManager,
163 > persistenceVisibilityManager: args.PersistenceVisibilityManager,
164 > historyServiceResolver: args.HistoryServiceResolver,
165 > metricsHandler: args.MetricsHandler,
166 > payloadSerializer: args.PayloadSerializer,
167 > timeSource: args.TimeSource,
168 > namespaceRegistry: args.NamespaceRegistry,
169 > saProvider: args.SaProvider,
170 > clusterMetadata: args.ClusterMetadata,
171 > archivalMetadata: args.ArchivalMetadata,
172 > hostInfoProvider: args.HostInfoProvider,
173 > controller: args.ShardController,
174 > eventNotifier: args.EventNotifier,
175 > tracer: args.TracerProvider.Tracer(consts.LibraryName),
176 > taskQueueManager: args.TaskQueueManager,
177 > taskCategoryRegistry: args.TaskCategoryRegistry,
178 > dlqMetricsEmitter: args.DLQMetricsEmitter,
179 > chasmEngine: args.ChasmEngine,
180 > chasmRegistry: args.ChasmRegistry,
181 > testHooks: args.TestHooks,
182 >
183 > replicationTaskFetcherFactory: args.ReplicationTaskFetcherFactory,
184 > replicationTaskConverterProvider: args.ReplicationTaskConverterFactory,
185 > streamReceiverMonitor: args.StreamReceiverMonitor,
186 > replicationServerRateLimiter: args.ReplicationServerRateLimiter,
187 > }
188 >
189 > // Build the Nexus handler in OnStart rather than here so that it runs after all
190 > // fx.Invoke functions have completed. If we built it eagerly, the dependency chain
191 > //
192 > // activity.HistoryModule (fx.Invoke)
193 > // → *library → *handler → historyservice.HistoryServiceServer
194 > // → HistoryServiceServerProvider → HandlerProvider (this function)
195 > //
196 > // would force HandlerProvider to run before modules like chasmtests.Module have had
197 > // a chance to register their nexus services via their own fx.Invoke calls. As a
198 > // result, buildNexusHandler would snapshot an empty registry and h.nexusHandler
199 > // would remain nil, causing all StartNexusOperation calls to the system endpoint to
200 > // return "no nexus services registered". OnStart hooks run after ALL invokes are
201 > // done, so the registry is fully populated by the time we call buildNexusHandler.
202 > lc.Append(fx.Hook{
203 > OnStart: func(_ context.Context) error {
204 > h, err := buildNexusHandler(args.ChasmRegistry) fx.go
205 > if err != nil {
206 return err
207 }
208 > handler.nexusHandler = h fx.go
209 > return nil
210 },
211 })
212
213 > return handler, nil fx.go
214 }
215
216 > func buildNexusHandler(chasmRegistry *chasm.Registry) (nexus.Handler, error) { fx.go
217 > nexusServices := chasmRegistry.NexusServices()
218 > if len(nexusServices) == 0 {
219 return nil, nil
220 }
221 > serviceRegistry := nexus.NewServiceRegistry() fx.go
222 > for _, svc := range nexusServices {
223 > // No chance of collision here since the registry would have errored out earlier.
224 > serviceRegistry.MustRegister(svc)
225 > }
226
227 > return serviceRegistry.NewHandler() fx.go
228 }
229
230 func HistoryEngineFactoryProvider(
231 params HistoryEngineFactoryParams,
232 > ) shard.EngineFactory { fx.go
233 > return &historyEngineFactory{
234 > HistoryEngineFactoryParams: params,
235 > }
236 > }
237
238 func ConfigProvider(
239 dc *dynamicconfig.Collection,
240 persistenceConfig config.Persistence,
241 > ) *configs.Config { fx.go
242 > return configs.NewConfig(
243 > dc,
244 > persistenceConfig.NumHistoryShards,
245 > )
246 > }
247
248 func ServiceErrorInterceptorProvider(
249 dc *dynamicconfig.Collection,
250 > ) *interceptor.ServiceErrorInterceptor { fx.go
251 > return interceptor.NewServiceErrorInterceptor(
252 > dynamicconfig.MaxServiceErrorMessageLength.Get(dc),
253 > )
254 > }
255
256 > func ThrottledLoggerRpsFnProvider(serviceConfig *configs.Config) resource.ThrottledLoggerRpsFn { fx.go
257 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
258 }
259
260 > func RetryableInterceptorProvider() *interceptor.RetryableInterceptor { fx.go
261 > return interceptor.NewRetryableInterceptor(
262 > common.CreateHistoryHandlerRetryPolicy(),
263 > api.IsRetryableError,
264 > )
265 > }
266
267 func ErrorHandlerProvider(
268 logger log.Logger,
269 serviceConfig *configs.Config,
270 > ) *interceptor.RequestErrorHandler { fx.go
271 > return interceptor.NewRequestErrorHandler(
272 > logger,
273 > serviceConfig.LogAllReqErrors,
274 > )
275 > }
276
277 func TelemetryInterceptorProvider(
281 serviceConfig *configs.Config,
282 requestErrorHandler *interceptor.RequestErrorHandler,
283 > ) *interceptor.TelemetryInterceptor { fx.go
284 > return interceptor.NewTelemetryInterceptor(
285 > namespaceRegistry,
286 > metricsHandler,
287 > logger,
288 > serviceConfig.LogAllReqErrors,
289 > requestErrorHandler,
290 > )
291 > }
292
293 func HealthSignalAggregatorProvider(
294 dynamicCollection *dynamicconfig.Collection,
295 logger log.ThrottledLogger,
296 > ) interceptor.HealthSignalAggregator { fx.go
297 > return interceptor.NewHealthSignalAggregator(
298 > logger,
299 > dynamicconfig.HistoryHealthSignalMetricsEnabled.Get(dynamicCollection),
300 > dynamicconfig.HistoryHealthSignalUsePercentiles.Get(dynamicCollection),
301 > dynamicconfig.PersistenceHealthSignalWindowSize.Get(dynamicCollection)(),
302 > dynamicconfig.PersistenceHealthSignalBufferSize.Get(dynamicCollection)(),
303 > dynamicconfig.HistoryHealthSignalLatencyWindowSize.Get(dynamicCollection)(),
304 > dynamicconfig.HistoryHealthSignalLatencyWindowCount.Get(dynamicCollection)(),
305 > )
306 > }
307
308 func HealthCheckInterceptorProvider(
309 healthSignalAggregator interceptor.HealthSignalAggregator,
310 > ) *interceptor.HealthCheckInterceptor { fx.go
311 > return interceptor.NewHealthCheckInterceptor(
312 > healthSignalAggregator,
313 > )
314 > }
315
316 > func ContextMetadataInterceptorProvider(logger log.Logger) *interceptor.ContextMetadataInterceptor { fx.go
317 > return interceptor.NewContextMetadataInterceptor(true, logger)
318 > }
319
320 func HistoryAdditionalInterceptorsProvider(
322 chasmRequestEngineInterceptor *chasm.ChasmEngineInterceptor,
323 chasmRequestVisibilityInterceptor *chasm.ChasmVisibilityInterceptor,
324 > ) []grpc.UnaryServerInterceptor { fx.go
325 > return []grpc.UnaryServerInterceptor{
326 > healthCheckInterceptor.UnaryIntercept,
327 > chasmRequestEngineInterceptor.Intercept,
328 > chasmRequestVisibilityInterceptor.Intercept,
329 > }
330 > }
331
332 func NamespaceRateLimitInterceptorProvider(
334 namespaceRegistry namespace.Registry,
335 metricsHandler metrics.Handler,
336 > ) interceptor.NamespaceRateLimitInterceptor { fx.go
337 >
338 > namespaceRateFn := func(namespaceName string) float64 {
339 if namespaceRPS := serviceConfig.NamespaceRPS(namespaceName); namespaceRPS > 0 {
340 return float64(namespaceRPS)
344 }
345
346 > return interceptor.NewNamespaceRateLimitInterceptor( fx.go
347 > namespaceRegistry,
348 > configs.NewNamespaceRateLimiter(
349 > namespaceRateFn,
350 > serviceConfig.OperatorRPSRatio,
351 > ),
352 > map[string]int{}, // no token overrides
353 > map[string]struct{}{}, // no long polls on history service
354 > dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false), // no long poll methods
355 > metricsHandler,
356 > )
357 }
358
359 func RateLimitInterceptorProvider(
360 serviceConfig *configs.Config,
361 > ) *interceptor.RateLimitInterceptor { fx.go
362 > return interceptor.NewRateLimitInterceptor(
363 > configs.NewPriorityRateLimiter(func() float64 { return float64(serviceConfig.RPS()) }, serviceConfig.OperatorRPSRatio),
364 map[string]int{
365 healthpb.Health_Check_FullMethodName: 0, // exclude health check requests from rate limiting.
371 func ESProcessorConfigProvider(
372 serviceConfig *configs.Config,
373 > ) *elasticsearch.ProcessorConfig { fx.go
374 > return &elasticsearch.ProcessorConfig{
375 > IndexerConcurrency: serviceConfig.IndexerConcurrency,
376 > ESProcessorNumOfWorkers: serviceConfig.ESProcessorNumOfWorkers,
377 > ESProcessorBulkActions: serviceConfig.ESProcessorBulkActions,
378 > ESProcessorBulkSize: serviceConfig.ESProcessorBulkSize,
379 > ESProcessorFlushInterval: serviceConfig.ESProcessorFlushInterval,
380 > ESProcessorAckTimeout: serviceConfig.ESProcessorAckTimeout,
381 > }
382 > }
383
384 func PersistenceRateLimitingParamsProvider(
387 ownershipBasedQuotaScaler shard.LazyLoadedOwnershipBasedQuotaScaler,
388 logger log.SnTaggedLogger,
389 > ) service.PersistenceRateLimitingParams { fx.go
390 > hostCalculator := calculator.NewLoggedCalculator(
391 > shard.NewOwnershipAwareQuotaCalculator(
392 > ownershipBasedQuotaScaler,
393 > persistenceLazyLoadedServiceResolver,
394 > serviceConfig.PersistenceMaxQPS,
395 > serviceConfig.PersistenceGlobalMaxQPS,
396 > ),
397 > log.With(logger, tag.ComponentPersistence, tag.ScopeHost),
398 > )
399 > namespaceCalculator := calculator.NewLoggedNamespaceCalculator(
400 > shard.NewOwnershipAwareNamespaceQuotaCalculator(
401 > ownershipBasedQuotaScaler,
402 > persistenceLazyLoadedServiceResolver,
403 > serviceConfig.PersistenceNamespaceMaxQPS,
404 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
405 > ),
406 > log.With(logger, tag.ComponentPersistence, tag.ScopeNamespace),
407 > )
408 > return service.PersistenceRateLimitingParams{
409 > PersistenceMaxQps: func() int {
410 > return int(hostCalculator.GetQuota())
411 > },
412 PersistenceNamespaceMaxQps: func(namespace string) int {
413 return int(namespaceCalculator.GetQuota(namespace))
433 chasmRegistry *chasm.Registry,
434 serializer serialization.Serializer,
435 > ) (manager.VisibilityManager, error) { fx.go
436 > return visibility.NewManager(
437 > *persistenceConfig,
438 > persistenceServiceResolver,
439 > customVisibilityStoreFactory,
440 > esProcessorConfig,
441 > saProvider,
442 > searchAttributesMapperProvider,
443 > namespaceRegistry,
444 > chasmRegistry,
445 > serviceConfig.VisibilityPersistenceMaxReadQPS,
446 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
447 > serviceConfig.OperatorRPSRatio,
448 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
449 > serviceConfig.EnableReadFromSecondaryVisibility,
450 > serviceConfig.VisibilityEnableShadowReadMode,
451 > serviceConfig.SecondaryVisibilityWritingMode,
452 > serviceConfig.VisibilityDisableOrderByClause,
453 > serviceConfig.VisibilityEnableManualPagination,
454 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
455 > metricsHandler,
456 > logger,
457 > serializer,
458 > )
459 > }
460
461 func ChasmVisibilityManagerProvider(
475 metricsHandler metrics.Handler,
476 config *configs.Config,
477 > ) events.Notifier { fx.go
478 > return events.NewNotifier(
479 > timeSource,
480 > metricsHandler,
481 > config.GetShardID,
482 > )
483 > }
484
485 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
486 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
487 > }
488
489 func ReplicationProgressCacheProvider(
491 logger log.Logger,
492 handler metrics.Handler,
493 > ) replication.ProgressCache { fx.go
494 > return replication.NewProgressCache(serviceConfig, logger, handler)
495 > }
496
497 func VersionMembershipCacheProvider(
499 serviceConfig *configs.Config,
500 metricsHandler metrics.Handler,
501 > ) worker_versioning.VersionMembershipAndReactivationStatusCache { fx.go
502 > c := commoncache.New(serviceConfig.VersionMembershipCacheMaxSize(), &commoncache.Options{
503 > TTL: max(1*time.Second, serviceConfig.VersionMembershipCacheTTL()),
504 > })
505 > lc.Append(fx.Hook{
506 > OnStop: func(context.Context) error {
507 > c.Stop() fx.go
508 > return nil
509 > },
510 })
511 > return worker_versioning.NewVersionMembershipAndReactivationStatusCache(c, metricsHandler) fx.go
512 }
513
516 serviceConfig *configs.Config,
517 metricsHandler metrics.Handler,
518 > ) worker_versioning.RoutingInfoCache { fx.go
519 > c := commoncache.New(serviceConfig.RoutingInfoCacheMaxSize(), &commoncache.Options{
520 > TTL: max(1*time.Second, serviceConfig.RoutingInfoCacheTTL()),
521 > })
522 > lc.Append(fx.Hook{
523 > OnStop: func(context.Context) error {
524 > c.Stop() fx.go
525 > return nil
526 > },
527 })
528 > return worker_versioning.NewRoutingInfoCache(c, metricsHandler) fx.go
529 }
go.temporal.io/server/common/resource/fx.go 246 covered LOC · 45 ranges

Open complete file

89 fx.Provide(SearchAttributeManagerProvider),
90 fx.Provide(NamespaceRegistryProvider),
91 > fx.Provide(func() namespace.NamespaceStateChangedFn { return nsregistry.DefaultNamespaceStateChanged }), fx.go
92 nsregistry.RegistryLifetimeHooksModule,
93 fx.Provide(fx.Annotate(
94 > func(p namespace.Registry) pingable.Pingable { return p }, fx.go
95 fx.ResultTags(`group:"deadlockDetectorRoots"`),
96 )),
127 )
128
129 > func DefaultSnTaggedLoggerProvider(logger log.Logger, sn primitives.ServiceName) log.SnTaggedLogger { fx.go
130 > return log.With(logger, tag.Service(sn))
131 > }
132
133 func ThrottledLoggerProvider(
134 logger log.SnTaggedLogger,
135 fn ThrottledLoggerRpsFn,
136 > ) log.ThrottledLogger { fx.go
137 > return log.NewThrottledLogger(
138 > logger,
139 > quotas.RateFn(fn),
140 > )
141 > }
142
143 > func GrpcListenerProvider(factory common.RPCFactory) net.Listener { fx.go
144 > return factory.GetGRPCListener()
145 > }
146
147 > func HostNameProvider() (HostName, error) { fx.go
148 > hn, err := os.Hostname()
149 > return HostName(hn), err
150 > }
151
152 > func TimeSourceProvider() clock.TimeSource { fx.go
153 > return clock.NewRealTimeSource()
154 > }
155
156 func SearchAttributeMapperProviderProvider(
159 searchAttributeProvider searchattribute.Provider,
160 persistenceConfig *config.Persistence,
161 > ) searchattribute.MapperProvider { fx.go
162 > primaryVisibilityStoreConfig := persistenceConfig.GetVisibilityStoreConfig()
163 > return searchattribute.NewMapperProvider(
164 > saMapper,
165 > namespaceRegistry,
166 > searchAttributeProvider,
167 > primaryVisibilityStoreConfig.GetIndexName(),
168 > )
169 > }
170
171 func SearchAttributeProviderProvider(
174 cmMgr persistence.ClusterMetadataManager,
175 dynamicCollection *dynamicconfig.Collection,
176 > ) searchattribute.Provider { fx.go
177 > return searchattribute.NewManager(
178 > timeSource,
179 > cmMgr,
180 > logger,
181 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Get(dynamicCollection))
182 > }
183
184 func SearchAttributeManagerProvider(
187 cmMgr persistence.ClusterMetadataManager,
188 dynamicCollection *dynamicconfig.Collection,
189 > ) searchattribute.Manager { fx.go
190 > return searchattribute.NewManager(
191 > timeSource,
192 > cmMgr,
193 > logger,
194 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Get(dynamicCollection))
195 > }
196
197 // SearchAttributeValidatorProvider creates a new search attribute validator with the given dependencies. It configures
205 metricsHandler metrics.Handler,
206 logger log.Logger,
207 > ) *searchattribute.Validator { fx.go
208 > return searchattribute.NewValidator(
209 > saProvider,
210 > saMapperProvider,
211 > dynamicconfig.SearchAttributesNumberOfKeysLimit.Get(dynamicCollection),
212 > dynamicconfig.SearchAttributesSizeOfValueLimit.Get(dynamicCollection),
213 > dynamicconfig.SearchAttributesTotalSizeLimit.Get(dynamicCollection),
214 > visibilityMgr,
215 > visibility.AllowListForValidation(
216 > visibilityMgr.GetStoreNames(),
217 > dynamicconfig.VisibilityAllowList.Get(dynamicCollection),
218 > ),
219 > dynamicconfig.SuppressErrorSetSystemSearchAttribute.Get(dynamicCollection),
220 > metricsHandler,
221 > logger,
222 > )
223 > }
224
225 type NamespaceRegistryParams struct {
235 }
236
237 > func NamespaceRegistryProvider(params NamespaceRegistryParams) namespace.Registry { fx.go
238 > return nsregistry.NewRegistry(
239 > params.MetadataManager,
240 > params.ClusterMetadata.IsGlobalNamespaceEnabled(),
241 > params.ClusterMetadata.GetCurrentClusterName(),
242 > dynamicconfig.NamespaceCacheRefreshInterval.Get(params.DynamicCollection),
243 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Get(params.DynamicCollection),
244 > params.MetricsHandler,
245 > params.Logger,
246 > params.ReplicationResolverFactory,
247 > params.NamespaceStateChangedFn,
248 > )
249 > }
250
251 func ClientFactoryProvider(
259 logger log.SnTaggedLogger,
260 throttledLogger log.ThrottledLogger,
261 > ) client.Factory { fx.go
262 > return factoryProvider.NewFactory(
263 > rpcFactory,
264 > membershipMonitor,
265 > metricsHandler,
266 > dynamicCollection,
267 > testHooks,
268 > persistenceConfig.NumHistoryShards,
269 > logger,
270 > throttledLogger,
271 > )
272 > }
273
274 func ClientBeanProvider(
276 clientFactory client.Factory,
277 clusterMetadata cluster.Metadata,
278 > ) (client.Bean, error) { fx.go
279 > bean, err := client.NewClientBean(
280 > clientFactory,
281 > clusterMetadata,
282 > )
283 > if err != nil {
284 return nil, err
285 }
286 // Deterministically release the bean's clients (daemon goroutines and
287 // cached gRPC connections) on shutdown.
288 > lc.Append(fx.StopHook(bean.Close)) fx.go
289 > return bean, nil
290 }
291
292 > func FrontendClientProvider(clientBean client.Bean) workflowservice.WorkflowServiceClient { fx.go
293 > frontendRawClient := clientBean.GetFrontendClient()
294 > return frontend.NewRetryableClient(
295 > frontendRawClient,
296 > common.CreateFrontendClientRetryPolicy(),
297 > common.IsServiceClientTransientError,
298 > )
299 > }
300
301 > func AdminClientProvider(clientBean client.Bean, clusterMetadata cluster.Metadata) (adminservice.AdminServiceClient, error) { fx.go
302 > adminRawClient, err := clientBean.GetRemoteAdminClient(clusterMetadata.GetCurrentClusterName())
303 > if err != nil {
304 return nil, err
305 }
306 > return admin.NewRetryableClient( fx.go
307 > adminRawClient,
308 > common.CreateFrontendClientRetryPolicy(),
309 > common.IsServiceClientTransientError,
310 > ), nil
311 }
312
313 func RuntimeMetricsReporterProvider(
314 params RuntimeMetricsReporterParams,
315 > ) *metrics.RuntimeMetricsReporter { fx.go
316 > return metrics.NewRuntimeMetricsReporter(
317 > params.MetricHandler,
318 > time.Minute,
319 > params.Logger,
320 > string(params.InstanceID),
321 > )
322 > }
323
324 > func HistoryRawClientProvider(clientBean client.Bean) HistoryRawClient { fx.go
325 > return clientBean.GetHistoryClient()
326 > }
327
328 > func HistoryClientProvider(historyRawClient HistoryRawClient, dc *dynamicconfig.Collection) HistoryClient { fx.go
329 > return history.NewRetryableClient(
330 > historyRawClient,
331 > common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
332 > common.IsServiceClientTransientError,
333 > )
334 > }
335
336 func MatchingRawClientProvider(
337 clientBean client.Bean,
338 namespaceRegistry namespace.Registry,
339 > ) (MatchingRawClient, error) { fx.go
340 > return clientBean.GetMatchingClient(namespaceRegistry.GetNamespaceName)
341 > }
342
343 > func MatchingClientProvider(matchingRawClient MatchingRawClient, dc *dynamicconfig.Collection) MatchingClient { fx.go
344 > return matching.NewRetryableClient(
345 > matchingRawClient,
346 > common.CreateMatchingClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
347 > common.CreateMatchingClientLongPollRetryPolicy(),
348 > common.IsServiceClientTransientError,
349 > )
350 > }
351
352 > func PersistenceConfigProvider(persistenceConfig config.Persistence, dc *dynamicconfig.Collection) *config.Persistence { fx.go
353 > persistenceConfig.TransactionSizeLimit = dynamicconfig.TransactionSizeLimit.Get(dc)
354 > return &persistenceConfig
355 > }
356
357 > func ArchivalMetadataProvider(dc *dynamicconfig.Collection, cfg *config.Config) archiver.ArchivalMetadata { fx.go
358 > return archiver.NewArchivalMetadata(
359 > dc,
360 > cfg.Archival.History.State,
361 > cfg.Archival.History.EnableRead,
362 > cfg.Archival.Visibility.State,
363 > cfg.Archival.Visibility.EnableRead,
364 > &cfg.NamespaceDefaults.Archival,
365 > )
366 > }
367
368 func ArchiverProviderProvider(
373 logger log.SnTaggedLogger,
374 metricsHandler metrics.Handler,
375 > ) provider.ArchiverProvider { fx.go
376 > return provider.NewArchiverProvider(
377 > cfg.Archival.History.Provider,
378 > cfg.Archival.Visibility.Provider,
379 > customHistoryArchiverFactory,
380 > customVisibilityArchiverFactory,
381 > persistenceExecutionManager,
382 > logger,
383 > metricsHandler,
384 > )
385 > }
386
387 func SdkClientFactoryProvider(
392 resolver *membership.GRPCResolver,
393 dc *dynamicconfig.Collection,
394 > ) (sdk.ClientFactory, error) { fx.go
395 > frontendURL, _, _, frontendTLSConfig, err := getFrontendConnectionDetails(cfg, tlsConfigProvider, resolver)
396 > if err != nil {
397 return nil, err
398 }
399 > return sdk.NewClientFactory( fx.go
400 > frontendURL,
401 > frontendTLSConfig,
402 > metricsHandler,
403 > logger,
404 > dynamicconfig.WorkerStickyCacheSize.Get(dc),
405 > ), nil
406 }
407
408 > func DCRedirectionPolicyProvider(cfg *config.Config) config.DCRedirectionPolicy { fx.go
409 > return cfg.DCRedirectionPolicy
410 > }
411
412 func PerServiceDialOptionsProvider(
413 logger log.SnTaggedLogger,
414 > ) map[primitives.ServiceName][]grpc.DialOption { fx.go
415 > trailerInterceptor := interceptor.TrailerToContextMetadataInterceptor(logger)
416 > dialOpt := grpc.WithChainUnaryInterceptor(trailerInterceptor)
417 > return map[primitives.ServiceName][]grpc.DialOption{
418 > primitives.HistoryService: {dialOpt},
419 > primitives.MatchingService: {dialOpt},
420 > }
421 > }
422
423 func RPCFactoryProvider(
433 dc *dynamicconfig.Collection,
434 tokenProvider auth.TokenProvider,
435 > ) (common.RPCFactory, error) { fx.go
436 > frontendURL, frontendHTTPURL, frontendHTTPPort, frontendTLSConfig, err := getFrontendConnectionDetails(cfg, tlsConfigProvider, resolver)
437 > if err != nil {
438 return nil, err
439 }
440
441 > var options []grpc.DialOption fx.go
442 > if tracingStatsHandler != nil {
443 options = append(options, grpc.WithStatsHandler(tracingStatsHandler))
444 }
445 > enableServerKeepalive := dynamicconfig.EnableInternodeServerKeepAlive.Get(dc)() fx.go
446 > enableClientKeepalive := dynamicconfig.EnableInternodeClientKeepAlive.Get(dc)()
447 > factory := rpc.NewFactory(
448 > cfg,
449 > svcName,
450 > logger,
451 > metricsHandler,
452 > tlsConfigProvider,
453 > frontendURL,
454 > frontendHTTPURL,
455 > frontendHTTPPort,
456 > frontendTLSConfig,
457 > options,
458 > perServiceDialOptions,
459 > monitor,
460 > tokenProvider,
461 > )
462 > factory.EnableInternodeServerKeepalive = enableServerKeepalive
463 > factory.EnableInternodeClientKeepalive = enableClientKeepalive
464 > logger.Debug(fmt.Sprintf("RPC factory created. enableServerKeepalive: %v, enableClientKeepalive: %v", enableServerKeepalive, enableClientKeepalive))
465 > return factory, nil
466 }
467
469 metadata cluster.Metadata,
470 tlsConfigProvider encryption.TLSConfigProvider,
471 > ) *cluster.FrontendHTTPClientCache { fx.go
472 > return cluster.NewFrontendHTTPClientCache(metadata, tlsConfigProvider)
473 > }
474
475 func getFrontendConnectionDetails(
477 tlsConfigProvider encryption.TLSConfigProvider,
478 resolver *membership.GRPCResolver,
479 > ) (string, string, int, *tls.Config, error) { fx.go
480 > // To simplify the static config, we switch default values based on whether the config
481 > // defines an "internal-frontend" service. The default for TLS config can be overridden
482 > // with publicClient.forceTLSConfig.
483 > _, hasIFE := cfg.Services[string(primitives.InternalFrontendService)]
484 >
485 > forceTLS := cfg.PublicClient.ForceTLSConfig
486 > if forceTLS == config.ForceTLSConfigAuto {
487 > if hasIFE {
488 forceTLS = config.ForceTLSConfigInternode
489 > } else { fx.go
490 > forceTLS = config.ForceTLSConfigFrontend
491 > }
492 }
493
494 > var frontendTLSConfig *tls.Config fx.go
495 > var err error
496 > switch forceTLS {
497 case config.ForceTLSConfigInternode:
498 frontendTLSConfig, err = tlsConfigProvider.GetInternodeClientConfig()
499 > case config.ForceTLSConfigFrontend: fx.go
500 > frontendTLSConfig, err = tlsConfigProvider.GetFrontendClientConfig()
501 default:
502 err = fmt.Errorf("invalid forceTLSConfig")
503 }
504 > if err != nil { fx.go
505 return "", "", 0, nil, fmt.Errorf("unable to load TLS configuration: %w", err)
506 }
507
508 > frontendURL := cfg.PublicClient.HostPort fx.go
509 > if frontendURL == "" {
510 if hasIFE {
511 frontendURL = resolver.MakeURL(primitives.InternalFrontendService)
514 }
515 }
516 > frontendHTTPURL := cfg.PublicClient.HTTPHostPort fx.go
517 > if frontendHTTPURL == "" {
518 > if hasIFE {
519 frontendHTTPURL = resolver.MakeURL(primitives.InternalFrontendService)
520 > } else { fx.go
521 > frontendHTTPURL = resolver.MakeURL(primitives.FrontendService)
522 > }
523 }
524
525 > var frontendHTTPPort int fx.go
526 > if hasIFE {
527 frontendHTTPPort = cfg.Services[string(primitives.InternalFrontendService)].RPC.HTTPPort
528 > } else { fx.go
529 > frontendHTTPPort = cfg.Services[string(primitives.FrontendService)].RPC.HTTPPort
530 > }
531
532 > return frontendURL, frontendHTTPURL, frontendHTTPPort, frontendTLSConfig, nil fx.go
533 }
go.temporal.io/server/common/namespace/nsregistry/registry.go 243 covered LOC · 59 ranges

Open complete file

160 replicationResolverFactory namespace.ReplicationResolverFactory,
161 namespaceStateChangedFn namespace.NamespaceStateChangedFn,
162 > ) *registry { registry.go
163 > return &registry{
164 > persistence: aPersistence,
165 > globalNamespacesEnabled: enableGlobalNamespaces,
166 > currentClusterName: currentClusterName,
167 > clock: clock.NewRealTimeSource(),
168 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.NamespaceCacheScope)),
169 > logger: logger,
170 > nameToID: make(map[namespace.Name]namespace.ID),
171 > idToNamespace: make(map[namespace.ID]*namespace.Namespace),
172 > refreshInterval: refreshInterval,
173 > readthroughNotFoundCache: cache.New(readthroughCacheSize, &readthroughNotFoundCacheOpts),
174 >
175 > forceSearchAttributesCacheRefreshOnRead: forceSearchAttributesCacheRefreshOnRead,
176 > replicationResolverFactory: replicationResolverFactory,
177 > namespaceStateChangedFn: namespaceStateChangedFn,
178 > }
179 > }
180
181 // DefaultNamespaceStateChanged is the default implementation that checks whether a namespace
182 // state change is significant enough to trigger callbacks.
183 > func DefaultNamespaceStateChanged(currentClusterName string, oldNS *namespace.Namespace, newNS *namespace.Namespace) bool { registry.go
184 > return oldNS == nil ||
185 > oldNS.State() != newNS.State() ||
186 > oldNS.Name() != newNS.Name() ||
187 > oldNS.IsGlobalNamespace() != newNS.IsGlobalNamespace() ||
188 > //nolint:forbidigo // ns-wide state diff for cache invalidation.
189 > oldNS.ActiveInCluster(currentClusterName) != newNS.ActiveInCluster(currentClusterName) ||
190 > oldNS.ReplicationState("") != newNS.ReplicationState("")
191 > }
192
193 // GetRegistrySize observes the size of the by-name and by-ID maps.
215 // arrive. If not supported, falls back to periodic polling. Start blocks until the initial namespace refresh completes.
216 // The initial refresh must succeed or the function will fatal.
217 > func (r *registry) Start() { registry.go
218 > ctx := headers.SetCallerInfo(
219 > context.Background(),
220 > headers.SystemBackgroundHighCallerInfo,
221 > )
222 >
223 > watchStarted := false
224 > r.refresher, watchStarted = r.runWatchLoop(ctx)
225 > if watchStarted {
226 // Watch started successfully
227 return
228 }
229
230 > if err := r.refresher.Err(); !errors.Is(err, persistence.ErrWatchNotSupported) { registry.go
231 // Watch failed to start for a reason other than ErrWatchNotSupported
232 metrics.NamespaceRegistryWatchStartFailures.With(r.metricsHandler).Record(1)
233 r.logger.Warn("Unable to start namespace watch - falling back to polling", tag.Error(err))
234 > } else { registry.go
235 > r.logger.Info("Watch not supported by persistence, namespace registry will use polling")
236 > }
237
238 // Fall back to polling
239 > if err := r.refreshNamespaces(ctx); err != nil { registry.go
240 r.logger.Fatal("Unable to initialize namespace registry", tag.Error(err))
241 }
242 > r.refresher = goro.NewHandle(ctx).Go(r.runPollingLoop) registry.go
243 }
244
245 // Stop ends background refresh. Should only be invoked by fx lifecycle hook.
246 // Should not be called multiple times or concurrently with Start().
247 > func (r *registry) Stop() { registry.go
248 > // refresher may be nil if watch failed to start and we're shutting down.
249 > if r.refresher != nil {
250 > r.refresher.Cancel()
251 > <-r.refresher.Done()
252 > }
253 }
254
255 > func (r *registry) GetPingChecks() []pingable.Check { registry.go
256 > return []pingable.Check{
257 > {
258 > Name: "namespace registry lock",
259 > // we don't do any persistence ops, this shouldn't be blocked
260 > Timeout: 10 * time.Second,
261 > Ping: func() []pingable.Pingable {
262 > // just checking if we can acquire the lock
263 > r.nsMapsLock.Lock()
264 > // nolint:staticcheck
265 > r.nsMapsLock.Unlock()
266 > return nil
267 > },
268 MetricsName: metrics.DDNamespaceRegistryLockLatency.Name(),
269 },
271 }
272
273 > func (r *registry) GetAllNamespaces() []*namespace.Namespace { registry.go
274 > r.nsMapsLock.RLock()
275 > defer r.nsMapsLock.RUnlock()
276 > return expmaps.Values(r.idToNamespace)
277 > }
278
279 > func (r *registry) RegisterStateChangeCallback(key any, cb namespace.StateChangeCallbackFn) { registry.go
280 > // Store callback first to avoid race where watch events arrive between reading the namespace snapshot and storing the
281 > // callback. This ensures no events are missed, but introduces a different trade-off: The callback may receive duplicate
282 > // calls for the same namespace if a watch event arrives while we're iterating through the catch-up loop below. For
283 > // example:
284 > // 1. Callback is stored in stateChangeCallbacks
285 > // 2. Watch event arrives for namespace X, callback is invoked
286 > // 3. Catch-up loop reaches namespace X, callback is invoked again
287 > //
288 > // This is acceptable because callbacks are rarely added (so unlikely to trigger this) and callbacks should be idempotent anyway.
289 > callbackWithTiming := func(ns *namespace.Namespace, deletedFromDb bool) {
290 > // Track callback duration so we can identify slow callbacks
291 > start := time.Now()
292 > defer func() {
293 > duration := time.Since(start)
294 > if duration > slowCallbackDuration {
295 metrics.NamespaceRegistrySlowCallbacks.With(r.metricsHandler).Record(1)
296 r.logger.Warn(
302 }()
303
304 > cb(ns, deletedFromDb) registry.go
305 }
306
307 > r.stateChangeCallbacks.Store(key, namespace.StateChangeCallbackFn(callbackWithTiming)) registry.go
308 >
309 > r.nsMapsLock.RLock()
310 > allNamespaces := expmaps.Values(r.idToNamespace)
311 > r.nsMapsLock.RUnlock()
312 >
313 > // call once for each namespace already in the registry
314 > for _, ns := range allNamespaces {
315 > callbackWithTiming(ns, false) registry.go
316 > }
317 }
318
319 > func (r *registry) UnregisterStateChangeCallback(key any) { registry.go
320 > r.stateChangeCallbacks.Delete(key)
321 > }
322
323 // GetNamespace retrieves the information from the internal maps if it exists, otherwise retrieves the information from metadata
324 // store and update internal entries with an expiry before returning back
325 > func (r *registry) GetNamespace(name namespace.Name) (*namespace.Namespace, error) { registry.go
326 > if name == "" {
327 return nil, serviceerror.NewInvalidArgument("Namespace is empty.")
328 }
329 > return r.getOrReadthroughNamespace(name) registry.go
330 }
331
332 // GetNamespaceWithOptions retrieves a namespace entry by name, with behavior controlled by options.
333 > func (r *registry) GetNamespaceWithOptions(name namespace.Name, opts namespace.GetNamespaceOptions) (*namespace.Namespace, error) { registry.go
334 > if name == "" {
335 return nil, serviceerror.NewInvalidArgument("Namespace is empty.")
336 }
337 > if opts.DisableReadthrough { registry.go
338 > return r.getNamespace(name)
339 > }
340 return r.getOrReadthroughNamespace(name)
341 }
433 // On initial startup (initialWatch=true), retries are limited to avoid blocking server startup indefinitely.
434 // On reconnection after a previous success (initialWatch=false), retries continue indefinitely.
435 > func watchStartRetryPolicy(initialWatch bool) backoff.RetryPolicy { registry.go
436 > policy := backoff.NewExponentialRetryPolicy(CacheRefreshFailureRetryInterval)
437 > if initialWatch {
438 > return policy.WithMaximumAttempts(startWatchMaxAttempts)
439 > }
440 return policy.WithExpirationInterval(backoff.NoInterval)
441 }
447 // Uses ShutdownOnce to track whether the watch has ever started successfully, which affects retry behavior: limited
448 // retries on initial startup, unlimited on reconnection.
449 > func (r *registry) runWatchLoop(ctx context.Context) (*goro.Handle, bool) { registry.go
450 > // watchStartedOnce tracks whether the watch has ever started successfully.
451 > // Used to determine retry policy and signal to the caller when watch is ready.
452 > watchStartedOnce := channel.NewShutdownOnce()
453 >
454 > handle := goro.NewHandle(ctx).Go(
455 > func(ctx context.Context) error {
456 > // Outer loop handles watch restarts after connection failures.
457 > for {
458 > select {
459 case <-ctx.Done():
460 return nil
461 > default: registry.go
462 }
463
464 > result, err := r.startWatch(ctx, !watchStartedOnce.IsShutdown()) registry.go
465 > if err != nil {
466 > return err registry.go
467 > }
468
469 watchStartedOnce.Shutdown()
476 // Wait for either the watch to start successfully, or the goroutine to exit (due to error
477 // or because watch is not supported). Return true only if watch started successfully.
478 > select { registry.go
479 case <-watchStartedOnce.Channel():
480 return handle, true
481 > case <-handle.Done(): registry.go
482 > return handle, false
483 }
484 }
486 // startWatch attempts to establish a namespace watch with retries.
487 // Returns the watch channel and context on success.
488 > func (r *registry) startWatch(ctx context.Context, initialWatch bool) (watchStartResult, error) { registry.go
489 > return backoff.ThrottleRetryContextWithReturn(
490 > ctx,
491 > func(ctx context.Context) (startResult watchStartResult, err error) {
492 > // Create fresh watch context for this attempt
493 > watchCtx, watchCancel := context.WithCancel(ctx)
494 > defer func() {
495 > if err != nil {
496 > // Cancel attempt's watch context to clean up any partial watch state registry.go
497 > watchCancel()
498 > }
499 }()
500
501 > startResult.watchCtx = watchCtx registry.go
502 > startResult.watchCancel = watchCancel
503 >
504 > if startResult.eventCh, err = r.persistence.WatchNamespaces(watchCtx); err != nil {
505 > if !errors.Is(err, persistence.ErrWatchNotSupported) { registry.go
506 r.logger.Error("Error starting namespace watch", tag.Error(err))
507 }
508 > return registry.go
509 }
510
521 },
522 watchStartRetryPolicy(initialWatch),
523 > func(err error) bool { registry.go
524 > return !errors.Is(err, persistence.ErrWatchNotSupported)
525 > },
526 )
527 }
529 // runPollingLoop periodically refreshes the namespace cache.
530 // Used as fallback when namespace watches are not supported.
531 > func (r *registry) runPollingLoop(ctx context.Context) error { registry.go
532 > timer := time.NewTimer(r.refreshInterval())
533 >
534 > for {
535 > select {
536 > case <-ctx.Done(): registry.go
537 > return nil
538
539 case <-timer.C:
554 }
555
556 > func (r *registry) refreshNamespaces(ctx context.Context) (err error) { registry.go
557 > start := time.Now()
558 > defer func() {
559 > if err != nil {
560 metrics.NamespaceRegistryRefreshFailures.With(r.metricsHandler).Record(1)
561 }
562 > metrics.NamespaceRegistryRefreshLatency.With(r.metricsHandler).Record(time.Since(start)) registry.go
563 }()
564
565 > request := &persistence.ListNamespacesRequest{ registry.go
566 > PageSize: CacheRefreshPageSize,
567 > IncludeDeleted: true,
568 > }
569 > var namespacesDb namespace.Namespaces
570 > namespaceIDsDb := make(map[namespace.ID]struct{})
571 >
572 > for {
573 > // TODO: consider adding a timeout and/or retries here - long ListNamespaces
574 > // calls could delay watch reconnection or block shutdown
575 > response, err := r.persistence.ListNamespaces(ctx, request)
576 > if err != nil {
577 return err
578 }
579 > for _, namespaceDb := range response.Namespaces { registry.go
580 > ns, err := namespace.FromPersistentState( registry.go
581 > namespaceDb.Namespace,
582 > r.replicationResolverFactory(namespaceDb.Namespace),
583 > namespace.WithGlobalFlag(namespaceDb.IsGlobalNamespace),
584 > namespace.WithNotificationVersion(namespaceDb.NotificationVersion),
585 > )
586 > if err != nil {
587 return err
588 }
589 > namespacesDb = append(namespacesDb, ns) registry.go
590 > namespaceIDsDb[namespace.ID(namespaceDb.Namespace.Info.Id)] = struct{}{}
591 }
592 > if len(response.NextPageToken) == 0 { registry.go
593 > break
594 }
595 request.NextPageToken = response.NextPageToken
597
598 // Make a copy of the existing namespace maps (excluding deleted), so we can calculate diff and do atomic swap.
599 > newNameToID := make(map[namespace.Name]namespace.ID) registry.go
600 > newIDToNamespace := make(map[namespace.ID]*namespace.Namespace)
601 >
602 > var deletedEntries []*namespace.Namespace
603 > for _, ns := range r.GetAllNamespaces() {
604 if _, namespaceExistsDb := namespaceIDsDb[ns.ID()]; !namespaceExistsDb {
605 deletedEntries = append(deletedEntries, ns)
610 }
611
612 > var stateChanged []*namespace.Namespace registry.go
613 > for _, aNamespace := range namespacesDb {
614 > oldNS := r.updateIDToNamespace(newIDToNamespace, aNamespace.ID(), aNamespace) registry.go
615 > // If namespace was renamed, remove entry for the old name
616 > if oldNS != nil && oldNS.Name() != aNamespace.Name() {
617 delete(newNameToID, oldNS.Name())
618 }
619 > newNameToID[aNamespace.Name()] = aNamespace.ID() registry.go
620 >
621 > if r.namespaceStateChanged(oldNS, aNamespace) {
622 > stateChanged = append(stateChanged, aNamespace)
623 > }
624 }
625
626 > r.nsMapsLock.Lock() registry.go
627 > totalNamespaceCount := len(newIDToNamespace) // record metric value within lock boundary
628 > r.idToNamespace = newIDToNamespace
629 > r.nameToID = newNameToID
630 > stateChanged = append(stateChanged, r.stateChangedDuringReadthrough...)
631 > r.stateChangedDuringReadthrough = nil
632 > r.nsMapsLock.Unlock()
633 >
634 > metrics.TotalNamespaces.With(r.metricsHandler).Record(float64(totalNamespaceCount))
635 >
636 > r.stateChangeCallbacks.Range(
637 > func(_, value any) bool {
638 > //revive:disable-next-line:unchecked-type-assertion registry.go
639 > cb := value.(namespace.StateChangeCallbackFn)
640 >
641 > for _, ns := range deletedEntries {
642 cb(ns, true)
643 }
644 > for _, ns := range stateChanged { registry.go
645 > cb(ns, false) registry.go
646 > }
647
648 > return true registry.go
649 })
650
651 > return nil registry.go
652 }
653
714 id namespace.ID,
715 newNS *namespace.Namespace,
716 > ) *namespace.Namespace { registry.go
717 > oldNS := iDToNamespace[id]
718 > iDToNamespace[id] = newNS
719 > return oldNS
720 > }
721
722 // getNamespace retrieves the information from the cache if it exists
723 > func (r *registry) getNamespace(name namespace.Name) (*namespace.Namespace, error) { registry.go
724 > r.nsMapsLock.RLock()
725 > defer r.nsMapsLock.RUnlock()
726 > if id, ok := r.nameToID[name]; ok {
727 > return r.getNamespaceByIDLocked(id) registry.go
728 > }
729 return nil, serviceerror.NewNamespaceNotFound(name.String())
730 }
737 }
738
739 > func (r *registry) getNamespaceByIDLocked(id namespace.ID) (*namespace.Namespace, error) { registry.go
740 > if ns, ok := r.idToNamespace[id]; ok {
741 > return ns, nil registry.go
742 > }
743 return nil, serviceerror.NewNamespaceNotFound(id.String())
744 }
746 // getOrReadthroughNamespace returns namespace information if it exists or reads through
747 // to the persistence layer and updates internal entry if it doesn't
748 > func (r *registry) getOrReadthroughNamespace(name namespace.Name) (*namespace.Namespace, error) { registry.go
749 > // check main caches
750 > ns, err := r.getNamespace(name)
751 > if err == nil {
752 > return ns, nil registry.go
753 > }
754
755 r.readthroughLock.Lock()
894 }
895
896 > func (r *registry) namespaceStateChanged(oldNS *namespace.Namespace, newNS *namespace.Namespace) bool { registry.go
897 > return r.namespaceStateChangedFn(r.currentClusterName, oldNS, newNS)
898 > }
go.temporal.io/server/service/frontend/service.go 241 covered LOC · 11 ranges

Open complete file

267 dc *dynamicconfig.Collection,
268 numHistoryShards int32,
269 > ) *Config { service.go
270 > return &Config{
271 > NumHistoryShards: numHistoryShards,
272 > PersistenceMaxQPS: dynamicconfig.FrontendPersistenceMaxQPS.Get(dc),
273 > PersistenceGlobalMaxQPS: dynamicconfig.FrontendPersistenceGlobalMaxQPS.Get(dc),
274 > PersistenceNamespaceMaxQPS: dynamicconfig.FrontendPersistenceNamespaceMaxQPS.Get(dc),
275 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.FrontendPersistenceGlobalNamespaceMaxQPS.Get(dc),
276 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.DefaultPerShardNamespaceRPSMax,
277 > PersistenceDynamicRateLimitingParams: dynamicconfig.FrontendPersistenceDynamicRateLimitingParams.Get(dc),
278 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
279 >
280 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
281 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
282 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
283 > VisibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
284 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
285 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
286 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
287 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
288 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
289 > VisibilityAllowList: dynamicconfig.VisibilityAllowList.Get(dc),
290 > SuppressErrorSetSystemSearchAttribute: dynamicconfig.SuppressErrorSetSystemSearchAttribute.Get(dc),
291 >
292 > HistoryMaxPageSize: dynamicconfig.FrontendHistoryMaxPageSize.Get(dc),
293 > RPS: dynamicconfig.FrontendRPS.Get(dc),
294 > GlobalRPS: dynamicconfig.FrontendGlobalRPS.Get(dc),
295 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
296 > NamespaceReplicationInducingAPIsRPS: dynamicconfig.FrontendNamespaceReplicationInducingAPIsRPS.Get(dc),
297 >
298 > MaxNamespaceRPSPerInstance: dynamicconfig.FrontendMaxNamespaceRPSPerInstance.Get(dc),
299 > MaxNamespaceBurstRatioPerInstance: dynamicconfig.FrontendMaxNamespaceBurstRatioPerInstance.Get(dc),
300 > MaxConcurrentLongRunningRequestsPerInstance: dynamicconfig.FrontendMaxConcurrentLongRunningRequestsPerInstance.Get(dc),
301 > MaxGlobalConcurrentLongRunningRequests: dynamicconfig.FrontendGlobalMaxConcurrentLongRunningRequests.Get(dc),
302 > PollWaitForNamespaceRateLimitToken: dynamicconfig.PollWaitForNamespaceRateLimitToken.Get(dc),
303 > MaxNamespaceVisibilityRPSPerInstance: dynamicconfig.FrontendMaxNamespaceVisibilityRPSPerInstance.Get(dc),
304 > MaxNamespaceVisibilityBurstRatioPerInstance: dynamicconfig.FrontendMaxNamespaceVisibilityBurstRatioPerInstance.Get(dc),
305 > MaxNamespaceNamespaceReplicationInducingAPIsRPSPerInstance: dynamicconfig.FrontendMaxNamespaceNamespaceReplicationInducingAPIsRPSPerInstance.Get(dc),
306 > MaxNamespaceNamespaceReplicationInducingAPIsBurstRatioPerInstance: dynamicconfig.FrontendMaxNamespaceNamespaceReplicationInducingAPIsBurstRatioPerInstance.Get(dc),
307 > GlobalWorkerDeploymentReadRPS: dynamicconfig.FrontendGlobalWorkerDeploymentReadRPS.Get(dc),
308 > GlobalWorkerDeploymentReadBurstRatio: dynamicconfig.FrontendGlobalWorkerDeploymentReadBurstRatio.Get(dc),
309 >
310 > GlobalNamespaceRPS: dynamicconfig.FrontendGlobalNamespaceRPS.Get(dc),
311 > InternalFEGlobalNamespaceRPS: dynamicconfig.InternalFrontendGlobalNamespaceRPS.Get(dc),
312 > GlobalNamespaceVisibilityRPS: dynamicconfig.FrontendGlobalNamespaceVisibilityRPS.Get(dc),
313 > InternalFEGlobalNamespaceVisibilityRPS: dynamicconfig.InternalFrontendGlobalNamespaceVisibilityRPS.Get(dc),
314 > // Overshoot since these low rate limits don't work well in an uncoordinated global limiter.
315 > GlobalNamespaceNamespaceReplicationInducingAPIsRPS: dynamicconfig.FrontendGlobalNamespaceNamespaceReplicationInducingAPIsRPS.Get(dc),
316 >
317 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
318 > WorkerBuildIdSizeLimit: dynamicconfig.WorkerBuildIdSizeLimit.Get(dc),
319 > ReachabilityTaskQueueScanLimit: dynamicconfig.ReachabilityTaskQueueScanLimit.Get(dc),
320 > ReachabilityQueryBuildIdLimit: dynamicconfig.ReachabilityQueryBuildIdLimit.Get(dc),
321 > ReachabilityCacheOpenWFsTTL: dynamicconfig.ReachabilityCacheOpenWFsTTL.Get(dc),
322 > ReachabilityCacheClosedWFsTTL: dynamicconfig.ReachabilityCacheClosedWFsTTL.Get(dc),
323 > ReachabilityQuerySetDurationSinceDefault: dynamicconfig.ReachabilityQuerySetDurationSinceDefault.Get(dc),
324 > MaxBadBinaries: dynamicconfig.FrontendMaxBadBinaries.Get(dc),
325 > DisableListVisibilityByFilter: dynamicconfig.DisableListVisibilityByFilter.Get(dc),
326 > BlobSizeLimitError: dynamicconfig.BlobSizeLimitError.Get(dc),
327 > BlobSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
328 > MemoSizeLimitError: dynamicconfig.MemoSizeLimitError.Get(dc),
329 > ThrottledLogRPS: dynamicconfig.FrontendThrottledLogRPS.Get(dc),
330 > ShutdownDrainDuration: dynamicconfig.FrontendShutdownDrainDuration.Get(dc),
331 > ShutdownFailHealthCheckDuration: dynamicconfig.FrontendShutdownFailHealthCheckDuration.Get(dc),
332 > EnableNamespaceNotActiveAutoForwarding: dynamicconfig.EnableNamespaceNotActiveAutoForwarding.Get(dc),
333 > ForceNamespaceSelectedAPIAutoForwarding: dynamicconfig.ForceNamespaceSelectedAPIAutoForwarding.Get(dc),
334 > NamespaceMinRetentionLocal: dynamicconfig.NamespaceMinRetentionLocal.Get(dc),
335 > NamespaceMinRetentionGlobal: dynamicconfig.NamespaceMinRetentionGlobal.Get(dc),
336 > SearchAttributesNumberOfKeysLimit: dynamicconfig.SearchAttributesNumberOfKeysLimit.Get(dc),
337 > SearchAttributesSizeOfValueLimit: dynamicconfig.SearchAttributesSizeOfValueLimit.Get(dc),
338 > SearchAttributesTotalSizeLimit: dynamicconfig.SearchAttributesTotalSizeLimit.Get(dc),
339 > VisibilityArchivalQueryMaxPageSize: dynamicconfig.VisibilityArchivalQueryMaxPageSize.Get(dc),
340 > DisallowQuery: dynamicconfig.DisallowQuery.Get(dc),
341 > SendRawWorkflowHistory: dynamicconfig.SendRawWorkflowHistory.Get(dc),
342 > DefaultWorkflowRetryPolicy: dynamicconfig.DefaultWorkflowRetryPolicy.Get(dc),
343 > DefaultWorkflowTaskTimeout: dynamicconfig.DefaultWorkflowTaskTimeout.Get(dc),
344 > EnableServerVersionCheck: dynamicconfig.EnableServerVersionCheck.Get(dc),
345 > EnableTokenNamespaceEnforcement: dynamicconfig.EnableTokenNamespaceEnforcement.Get(dc),
346 > ExposeAuthorizerErrors: dynamicconfig.ExposeAuthorizerErrors.Get(dc),
347 > KeepAliveMinTime: dynamicconfig.KeepAliveMinTime.Get(dc),
348 > KeepAlivePermitWithoutStream: dynamicconfig.KeepAlivePermitWithoutStream.Get(dc),
349 > KeepAliveMaxConnectionIdle: dynamicconfig.KeepAliveMaxConnectionIdle.Get(dc),
350 > KeepAliveMaxConnectionAge: dynamicconfig.KeepAliveMaxConnectionAge.Get(dc),
351 > KeepAliveMaxConnectionAgeGrace: dynamicconfig.KeepAliveMaxConnectionAgeGrace.Get(dc),
352 > KeepAliveTime: dynamicconfig.KeepAliveTime.Get(dc),
353 > KeepAliveTimeout: dynamicconfig.KeepAliveTimeout.Get(dc),
354 >
355 > DeleteNamespaceDeleteActivityRPS: dynamicconfig.DeleteNamespaceDeleteActivityRPS.Get(dc),
356 > DeleteNamespacePageSize: dynamicconfig.DeleteNamespacePageSize.Get(dc),
357 > DeleteNamespacePagesPerExecution: dynamicconfig.DeleteNamespacePagesPerExecution.Get(dc),
358 > DeleteNamespaceConcurrentDeleteExecutionsActivities: dynamicconfig.DeleteNamespaceConcurrentDeleteExecutionsActivities.Get(dc),
359 > DeleteNamespaceNamespaceDeleteDelay: dynamicconfig.DeleteNamespaceNamespaceDeleteDelay.Get(dc),
360 >
361 > MaxFairnessWeightOverrideConfigLimit: dynamicconfig.MatchingMaxFairnessKeyWeightOverrides.Get(dc),
362 >
363 > EnableSchedules: dynamicconfig.FrontendEnableSchedules.Get(dc),
364 > EnableChasm: dynamicconfig.EnableChasm.Get(dc),
365 > EnableCHASMSchedulerCreation: dynamicconfig.EnableCHASMSchedulerCreation.Get(dc),
366 > CHASMSchedulerCreationRolloutPercent: dynamicconfig.CHASMSchedulerCreationRolloutPercent.Get(dc),
367 > EnableCHASMSchedulerRouting: dynamicconfig.EnableCHASMSchedulerRouting.Get(dc),
368 > EnableCHASMSchedulerSentinels: dynamicconfig.EnableCHASMSchedulerSentinels.Get(dc),
369 >
370 > // [cleanup-wv-pre-release]
371 > EnableDeployments: dynamicconfig.EnableDeployments.Get(dc),
372 > EnableDeploymentVersions: dynamicconfig.EnableDeploymentVersions.Get(dc),
373 >
374 > EnableBatcher: dynamicconfig.FrontendEnableBatcher.Get(dc),
375 > MaxConcurrentBatchOperation: dynamicconfig.FrontendMaxConcurrentBatchOperationPerNamespace.Get(dc),
376 > MaxExecutionCountBatchOperation: dynamicconfig.FrontendMaxExecutionCountBatchOperationPerNamespace.Get(dc),
377 > MaxConcurrentAdminBatchOperation: dynamicconfig.FrontendMaxConcurrentAdminBatchOperationPerNamespace.Get(dc),
378 > EnableBatchOperationsForStandaloneActivities: dynamicconfig.FrontendEnableBatchOperationsForStandaloneActivities.Get(dc),
379 >
380 > EnableUpdateWorkflowExecution: dynamicconfig.FrontendEnableUpdateWorkflowExecution.Get(dc),
381 > EnableUpdateWorkflowExecutionAsyncAccepted: dynamicconfig.FrontendEnableUpdateWorkflowExecutionAsyncAccepted.Get(dc),
382 > EnableWorkflowUpdateCallbacks: dynamicconfig.EnableWorkflowUpdateCallbacks.Get(dc),
383 > NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute: dynamicconfig.NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute.Get(dc),
384 >
385 > EnableWorkerVersioningData: dynamicconfig.FrontendEnableWorkerVersioningDataAPIs.Get(dc),
386 > EnableWorkerVersioningWorkflow: dynamicconfig.FrontendEnableWorkerVersioningWorkflowAPIs.Get(dc),
387 > EnableWorkerVersioningRules: dynamicconfig.FrontendEnableWorkerVersioningRuleAPIs.Get(dc),
388 >
389 > CallbackURLMaxLength: dynamicconfig.FrontendCallbackURLMaxLength.Get(dc),
390 > CallbackHeaderMaxSize: dynamicconfig.FrontendCallbackHeaderMaxSize.Get(dc),
391 > MaxCallbacksPerWorkflow: dynamicconfig.MaxCallbacksPerWorkflow.Get(dc),
392 > MaxNexusOperationTokenLength: nexusoperations.MaxOperationTokenLength.Get(dc),
393 > NexusRequestHeadersBlacklist: dynamicconfig.FrontendNexusRequestHeadersBlacklist.Get(dc),
394 > NexusForwardRequestUseEndpoint: dynamicconfig.FrontendNexusForwardRequestUseEndpointDispatch.Get(dc),
395 > NexusOperationsMetricTagConfig: nexusoperations.MetricTagConfiguration.Get(dc),
396 >
397 > LinkMaxSize: dynamicconfig.FrontendLinkMaxSize.Get(dc),
398 > MaxLinksPerRequest: dynamicconfig.FrontendMaxLinksPerRequest.Get(dc),
399 >
400 > CallbackEndpointConfigs: callback.AllowedAddresses.Get(dc),
401 > AdminEnableListHistoryTasks: dynamicconfig.AdminEnableListHistoryTasks.Get(dc),
402 >
403 > MaskInternalErrorDetails: dynamicconfig.FrontendMaskInternalErrorDetails.Get(dc),
404 >
405 > HistoryHostErrorPercentage: dynamicconfig.HistoryHostErrorPercentage.Get(dc),
406 > HistoryHostSelfErrorProportion: dynamicconfig.HistoryHostSelfErrorProportion.Get(dc),
407 > LogAllReqErrors: dynamicconfig.LogAllReqErrors.Get(dc),
408 > EnableEagerWorkflowStart: dynamicconfig.EnableEagerWorkflowStart.Get(dc),
409 > WorkflowRulesAPIsEnabled: dynamicconfig.WorkflowRulesAPIsEnabled.Get(dc),
410 > MaxWorkflowRulesPerNamespace: dynamicconfig.MaxWorkflowRulesPerNamespace.Get(dc),
411 > WorkerHeartbeatsEnabled: dynamicconfig.WorkerHeartbeatsEnabled.Get(dc),
412 > EnableCancelWorkerPollsOnShutdown: dynamicconfig.EnableCancelWorkerPollsOnShutdown.Get(dc),
413 > EnableMatchingFanOutForPollCancellation: dynamicconfig.EnableMatchingFanOutForPollCancellation.Get(dc),
414 > NumTaskQueueReadPartitions: dynamicconfig.MatchingNumTaskqueueReadPartitions.Get(dc),
415 > WorkerCommandsEnabled: dynamicconfig.WorkerCommandsEnabled.Get(dc),
416 > PollerAutoscalingAutoEnroll: dynamicconfig.PollerAutoscalingAutoEnroll.Get(dc),
417 > WorkflowPauseEnabled: dynamicconfig.WorkflowPauseEnabled.Get(dc),
418 > TimeSkippingEnabled: dynamicconfig.TimeSkippingEnabled.Get(dc),
419 > StandaloneNexusOperationsEnabled: chasmnexus.Enabled.Get(dc),
420 > EnableWorkflowTaskCompletionPagination: dynamicconfig.EnableWorkflowTaskCompletionPagination.Get(dc),
421 >
422 > HTTPAllowedHosts: dynamicconfig.FrontendHTTPAllowedHosts.Get(dc),
423 > AllowedExperiments: dynamicconfig.FrontendAllowedExperiments.Get(dc),
424 >
425 > Activity: activity.ConfigProvider(dc),
426 > }
427 > }
428
429 // Service represents the frontend service
460 metricsHandler metrics.Handler,
461 membershipMonitor membership.Monitor,
462 > ) *Service { service.go
463 > return &Service{
464 > config: serviceConfig,
465 > server: server,
466 > healthServer: healthServer,
467 > httpAPIServer: httpAPIServer,
468 > handler: handler,
469 > adminHandler: adminHandler,
470 > operatorHandler: operatorHandler,
471 > versionChecker: versionChecker,
472 > visibilityManager: visibilityMgr,
473 > logger: logger,
474 > grpcListener: grpcListener,
475 > metricsHandler: metricsHandler,
476 > membershipMonitor: membershipMonitor,
477 > }
478 > }
479
480 // Start starts the service
481 > func (s *Service) Start() { service.go
482 > s.logger.Info("frontend starting")
483 >
484 > healthpb.RegisterHealthServer(s.server, s.healthServer)
485 > workflowservice.RegisterWorkflowServiceServer(s.server, s.handler)
486 > adminservice.RegisterAdminServiceServer(s.server, s.adminHandler)
487 > operatorservice.RegisterOperatorServiceServer(s.server, s.operatorHandler)
488 >
489 > reflection.Register(s.server)
490 >
491 > // must start resource first
492 > metrics.RestartCount.With(s.metricsHandler).Record(1)
493 >
494 > s.versionChecker.Start()
495 > s.adminHandler.Start()
496 > s.operatorHandler.Start()
497 > s.handler.Start()
498 >
499 > go func() {
500 > s.logger.Info("Starting to serve on frontend listener")
501 > if err := s.server.Serve(s.grpcListener); err != nil {
502 s.logger.Fatal("Failed to serve on frontend listener", tag.Error(err))
503 }
504 }()
505
506 > if s.httpAPIServer != nil { service.go
507 go func() {
508 if err := s.httpAPIServer.Serve(); err != nil {
510 }
511 }()
512 > } else { service.go
513 > s.logger.Warn("HTTP API port has not been set. Nexus HTTP endpoints will not be available. " +
514 > "To enable Nexus, follow these instructions: https://github.com/temporalio/temporal/blob/main/docs/architecture/nexus.md#enabling-nexus.")
515 > }
516
517 > go s.membershipMonitor.Start() service.go
518 }
519
520 // Stop stops the service
521 > func (s *Service) Stop() { service.go
522 > // initiate graceful shutdown:
523 > // 1. Fail rpc health check, this will cause client side load balancer to stop forwarding requests to this node
524 > // 2. wait for failure detection time
525 > // 3. stop taking new requests by returning InternalServiceError
526 > // 4. Wait for X second
527 > // 5. Stop everything forcefully and return
528 >
529 > requestDrainTime := max(time.Second, s.config.ShutdownDrainDuration())
530 > failureDetectionTime := max(0, s.config.ShutdownFailHealthCheckDuration())
531 >
532 > s.logger.Info("ShutdownHandler: Updating gRPC health status to ShuttingDown")
533 > s.healthServer.Shutdown()
534 > s.membershipMonitor.SetDraining(true)
535 >
536 > s.logger.Info("ShutdownHandler: Waiting for others to discover I am unhealthy")
537 > time.Sleep(failureDetectionTime)
538 >
539 > s.handler.Stop()
540 > s.operatorHandler.Stop()
541 > s.adminHandler.Stop()
542 > s.versionChecker.Stop()
543 > s.visibilityManager.Close()
544 >
545 > s.logger.Info("ShutdownHandler: Draining traffic")
546 > // Gracefully stop gRPC server and HTTP API server concurrently
547 > var wg sync.WaitGroup
548 > wg.Go(func() {
549 > t := time.AfterFunc(requestDrainTime, func() {
550 s.logger.Info("ShutdownHandler: Drain time expired, stopping all traffic")
551 s.server.Stop()
552 })
553 > s.server.GracefulStop() service.go
554 > t.Stop()
555 })
556 > if s.httpAPIServer != nil { service.go
557 wg.Go(func() {
558 s.httpAPIServer.GracefulStop(requestDrainTime)
559 })
560 }
561 > wg.Wait() service.go
562 >
563 > if s.metricsHandler != nil {
564 > s.metricsHandler.Stop(s.logger)
565 > }
566
567 > s.logger.Info("frontend stopped") service.go
568 }
go.temporal.io/server/service/history/shard/controller_impl.go 232 covered LOC · 58 ranges

Open complete file

75 hostInfoProvider membership.HostInfoProvider,
76 contextFactory ContextFactory,
77 > ) *ControllerImpl { controller_impl.go
78 > hostIdentity := hostInfoProvider.HostInfo().Identity()
79 > contextTaggedLogger := log.With(logger, tag.ComponentShardController, tag.Address(hostIdentity))
80 > taggedMetricsHandler := metricsHandler.WithTags(metrics.OperationTag(metrics.HistoryShardControllerScope))
81 >
82 > ownership := newOwnership(
83 > config,
84 > historyServiceResolver,
85 > hostInfoProvider,
86 > contextTaggedLogger,
87 > taggedMetricsHandler,
88 > )
89 >
90 > c := &ControllerImpl{
91 > config: config,
92 > contextFactory: contextFactory,
93 > contextTaggedLogger: contextTaggedLogger,
94 > historyShards: make(map[int32]historyi.ControllableContext),
95 > hostInfoProvider: hostInfoProvider,
96 > ownership: ownership,
97 > taggedMetricsHandler: taggedMetricsHandler,
98 > shardCountSubscriptions: map[*shardCountSubscription]struct{}{},
99 > initialShardsAcquired: future.NewFuture[struct{}](),
100 > }
101 > c.lingerState.shards = make(map[historyi.ControllableContext]struct{})
102 > return c
103 > }
104
105 > func (c *ControllerImpl) Start() { controller_impl.go
106 > if !atomic.CompareAndSwapInt32(
107 > &c.status,
108 > common.DaemonStatusInitialized,
109 > common.DaemonStatusStarted,
110 > ) {
111 return
112 }
113
114 > c.ownership.start(c) controller_impl.go
115 >
116 > c.contextTaggedLogger.Info("", tag.LifeCycleStarted)
117 }
118
119 > func (c *ControllerImpl) Stop() { controller_impl.go
120 > if !atomic.CompareAndSwapInt32(
121 > &c.status,
122 > common.DaemonStatusStarted,
123 > common.DaemonStatusStopped,
124 > ) {
125 return
126 }
127
128 > c.initialShardsAcquired.SetIfNotReady(struct{}{}, context.Canceled) controller_impl.go
129 >
130 > c.ownership.stop()
131 >
132 > c.doShutdown()
133 >
134 > c.contextTaggedLogger.Info("", tag.LifeCycleStopped)
135 }
136
137 > func (c *ControllerImpl) GetPingChecks() []pingable.Check { controller_impl.go
138 > return []pingable.Check{{
139 > Name: "shard controller",
140 > Timeout: 10 * time.Second,
141 > Ping: func() []pingable.Pingable {
142 > // we only need to read but get write lock to make sure we can
143 > c.Lock()
144 > defer c.Unlock()
145 > out := make([]pingable.Pingable, 0, len(c.historyShards))
146 > for _, shard := range c.historyShards {
147 > out = append(out, shard)
148 > }
149 > return out
150 },
151 MetricsName: metrics.DDShardControllerLockLatency.Name(),
157 }
158
159 > func (c *ControllerImpl) InitialShardsAcquired(ctx context.Context) error { controller_impl.go
160 > _, err := c.initialShardsAcquired.Get(ctx)
161 > return err
162 > }
163
164 // GetShardByNamespaceWorkflow returns a shard context for the given namespace and workflow.
178 func (c *ControllerImpl) GetShardByID(
179 shardID int32,
180 > ) (historyi.ShardContext, error) { controller_impl.go
181 > startTime := time.Now().UTC()
182 > defer func() {
183 > metrics.GetEngineForShardLatency.With(c.taggedMetricsHandler).Record(time.Since(startTime))
184 > }()
185
186 > return c.getOrCreateShardContext(shardID) controller_impl.go
187 }
188
201 }
202
203 > func (c *ControllerImpl) ShardIDs() []int32 { controller_impl.go
204 > c.RLock()
205 > defer c.RUnlock()
206 >
207 > ids := make([]int32, 0, len(c.historyShards))
208 > for id := range c.historyShards {
209 ids = append(ids, id)
210 }
211 > return ids controller_impl.go
212 }
213
228 // if necessary. If a shard context is created, it will initialize in the background.
229 // This function won't block on rangeid lease acquisition.
230 > func (c *ControllerImpl) getOrCreateShardContext(shardID int32) (historyi.ControllableContext, error) { controller_impl.go
231 > if err := c.validateShardId(shardID); err != nil {
232 return nil, err
233 }
234 > c.RLock() controller_impl.go
235 > if shard, ok := c.historyShards[shardID]; ok {
236 > if shard.IsValid() { controller_impl.go
237 > c.RUnlock()
238 > return shard, nil
239 > }
240 // if shard not valid then proceed to create a new one
241 }
242 > c.RUnlock() controller_impl.go
243 >
244 > c.Lock()
245 > defer c.Unlock()
246 >
247 > // Check again with exclusive lock
248 > if shard, ok := c.historyShards[shardID]; ok {
249 if shard.IsValid() {
250 return shard, nil
256 }
257
258 > if err := c.ownership.verifyOwnership(shardID); err != nil { controller_impl.go
259 return nil, err
260 }
261
262 > if atomic.LoadInt32(&c.status) == common.DaemonStatusStopped { controller_impl.go
263 hostInfo := c.hostInfoProvider.HostInfo()
264 return nil, fmt.Errorf("ControllerImpl for host '%v' shutting down", hostInfo.Identity())
265 }
266
267 > shard, err := c.contextFactory.CreateContext(shardID, c.shardRemoveAndStop) controller_impl.go
268 > if err != nil {
269 return nil, err
270 }
271 > c.historyShards[shardID] = shard controller_impl.go
272 > metrics.ShardContextCreatedCounter.With(c.taggedMetricsHandler).Record(1)
273 > c.contextTaggedLogger.Info("", numShardsTag(len(c.historyShards)))
274 >
275 > return shard, nil
276 }
277
381 }
382
383 > func (c *ControllerImpl) acquireShards(ctx context.Context) { controller_impl.go
384 > metrics.AcquireShardsCounter.With(c.taggedMetricsHandler).Record(1)
385 > startTime := time.Now().UTC()
386 > defer func() {
387 > metrics.AcquireShardsLatency.With(c.taggedMetricsHandler).Record(time.Since(startTime))
388 > }()
389
390 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo) controller_impl.go
391 >
392 > // Readiness check: if we haven't marked readiness yet, then we need to set up a context to
393 > // run the readiness check on owned shards.
394 > var readinessCtx context.Context
395 > var readinessCancel context.CancelFunc
396 > if !c.initialShardsAcquired.Ready() {
397 > readinessCtx, readinessCancel = context.WithCancel(ctx)
398 > } else {
399 > readinessCancel = func() {} // we need a non-nil func for Swap controller_impl.go
400 }
401 // Cancel previous readiness check to ensure that the readiness check is always running on
402 // the most recent set of owned shards (e.g. after a membership change).
403 > if prevCancel := c.shardReadinessCancel.Swap(readinessCancel); prevCancel != nil { controller_impl.go
404 > prevCancel.(context.CancelFunc)() controller_impl.go
405 > }
406
407 > var ownedShardsLock sync.Mutex controller_impl.go
408 > var ownedShards []int32 // only populated if we are doing a readiness check
409 >
410 > tryAcquire := func(shardID int32) {
411 > if err := c.ownership.verifyOwnership(shardID); err != nil {
412 > if IsShardOwnershipLostError(err) { controller_impl.go
413 // current host is not owner of shard, unload it if it is already loaded.
414 if c.config.ShardLingerTimeLimit() > 0 {
418 }
419 }
420 > return controller_impl.go
421 }
422
423 > if readinessCtx != nil { controller_impl.go
424 > ownedShardsLock.Lock()
425 > ownedShards = append(ownedShards, shardID)
426 > ownedShardsLock.Unlock()
427 > }
428
429 > shard, err := c.GetShardByID(shardID) controller_impl.go
430 > if err != nil {
431 metrics.GetEngineForShardErrorCounter.With(c.taggedMetricsHandler).Record(1)
432 c.contextTaggedLogger.Error("Unable to create history shard context", tag.Error(err), tag.OperationFailed, tag.ShardID(shardID))
436 // Wait up to 1s for the shard to acquire the rangeid lock.
437 // After 1s we will move on but the shard will continue trying in the background.
438 > engineCtx, engineCancel := context.WithTimeout(ctx, 1*time.Second) controller_impl.go
439 > defer engineCancel()
440 > _, _ = shard.GetEngine(engineCtx)
441 }
442
443 > concurrency := int64(max(c.config.AcquireShardConcurrency(), 1)) controller_impl.go
444 > sem := semaphore.NewWeighted(concurrency)
445 > numShards := c.config.NumberOfShards
446 > randomStartOffset := rand.Int31n(numShards)
447 > for index := range numShards {
448 > shardID := (index+randomStartOffset)%numShards + 1
449 > if err := sem.Acquire(ctx, 1); err != nil {
450 break
451 }
452 > go func() { controller_impl.go
453 > defer sem.Release(1)
454 > tryAcquire(shardID)
455 > }()
456 }
457 > _ = sem.Acquire(ctx, concurrency) controller_impl.go
458 >
459 > c.RLock()
460 > // note that this count includes lingering shards
461 > numOfOwnedShards := len(c.historyShards)
462 > c.RUnlock()
463 > metrics.NumShardsGauge.With(c.taggedMetricsHandler).Record(float64(numOfOwnedShards))
464 > c.publishShardCountUpdate(numOfOwnedShards)
465 >
466 > // Readiness check: We should set initialShardsAcquired when:
467 > // 1. It's not already set.
468 > // 2. We should own at least one shard (i.e. not before we join membership).
469 > // 3. We have ownership of all the shards we're supposed to own.
470 > if readinessCtx != nil {
471 > if len(ownedShards) > 0 {
472 > go func() { controller_impl.go
473 > defer readinessCancel()
474 > if c.checkShardReadiness(readinessCtx, ownedShards) {
475 > c.initialShardsAcquired.SetIfNotReady(struct{}{}, nil) controller_impl.go
476 > }
477 }()
478 } else {
485 ctx context.Context,
486 shards []int32,
487 > ) bool { controller_impl.go
488 > concurrency := int64(max(c.config.AcquireShardConcurrency(), 1))
489 > sem := semaphore.NewWeighted(concurrency)
490 > var ready atomic.Int32
491 > for _, shardID := range shards {
492 > if sem.Acquire(ctx, 1) != nil {
493 return false
494 }
495 > go func() { controller_impl.go
496 > defer sem.Release(1)
497 > // Note that AssertOwnership uses a detached context for the actual persistence
498 > // op so we can't cancel it. If context is canceled, the final Acquire will
499 > // fail and we won't do anything.
500 > if shard, err := c.GetShardByID(shardID); err != nil {
501 return
502 > } else if _, err := shard.GetEngine(ctx); err != nil { controller_impl.go
503 return
504 > } else if shard.AssertOwnership(ctx) != nil { controller_impl.go
505 return
506 }
507 > ready.Add(1) controller_impl.go
508 }()
509 }
510 > if sem.Acquire(ctx, concurrency) != nil { controller_impl.go
511 return false
512 }
513
514 > if ready.Load() != int32(len(shards)) { controller_impl.go
515 c.contextTaggedLogger.Info("initial shards not ready",
516 tag.Int32("ready", ready.Load()), tag.Int("total", len(shards)))
517 return false
518 }
519 > c.contextTaggedLogger.Info("initial shards ready", tag.Int("total", len(shards))) controller_impl.go
520 > return true
521 }
522
523 // publishShardCountUpdate publishes the current number of shards that this controller owns to all shard count
524 // subscribers in a non-blocking manner.
525 > func (c *ControllerImpl) publishShardCountUpdate(shardCount int) { controller_impl.go
526 > c.RLock()
527 > defer c.RUnlock()
528 > for sub := range c.shardCountSubscriptions {
529 > select { controller_impl.go
530 > case sub.ch <- shardCount:
531 default:
532 }
534 }
535
536 > func (c *ControllerImpl) doShutdown() { controller_impl.go
537 > c.contextTaggedLogger.Info("", tag.LifeCycleStopping)
538 > c.Lock()
539 > defer c.Unlock()
540 > for _, shard := range c.historyShards {
541 > shard.FinishStop() controller_impl.go
542 > }
543 > c.historyShards = nil controller_impl.go
544 }
545
546 > func (c *ControllerImpl) validateShardId(shardID int32) error { controller_impl.go
547 > if shardID <= 0 {
548 return invalidShardIdLowerBound
549 }
550 > if shardID > c.config.NumberOfShards { controller_impl.go
551 return invalidShardIdUpperBound
552 }
553 > return nil controller_impl.go
554 }
555
556 // SubscribeShardCount returns a subscription to shard count updates with a 1-buffered channel. This method is thread-safe.
557 > func (c *ControllerImpl) SubscribeShardCount() ShardCountSubscription { controller_impl.go
558 > c.Lock()
559 > defer c.Unlock()
560 > sub := &shardCountSubscription{
561 > controller: c,
562 > ch: make(chan int, 1), // buffered because we do a non-blocking send
563 > }
564 > c.shardCountSubscriptions[sub] = struct{}{}
565 > return sub
566 > }
567
568 // ShardCount returns a channel that receives the current shard count. This channel will be closed when the subscription
569 // is canceled.
570 > func (s *shardCountSubscription) ShardCount() <-chan int { controller_impl.go
571 > return s.ch
572 > }
573
574 // Unsubscribe removes the subscription from the controller's list of subscriptions.
575 > func (s *shardCountSubscription) Unsubscribe() { controller_impl.go
576 > s.controller.Lock()
577 > defer s.controller.Unlock()
578 > if _, ok := s.controller.shardCountSubscriptions[s]; !ok {
579 return
580 }
581 > delete(s.controller.shardCountSubscriptions, s) controller_impl.go
582 > close(s.ch)
583 }
584
585 > func IsShardOwnershipLostError(err error) bool { controller_impl.go
586 > switch err.(type) {
587 case *persistence.ShardOwnershipLostError:
588 return true
go.temporal.io/server/common/membership/ringpop/service_resolver.go 226 covered LOC · 55 ranges

Open complete file

99 replicaPoints int,
100 logger log.Logger,
101 > ) *serviceResolver { service_resolver.go
102 > resolver := &serviceResolver{
103 > service: service,
104 > port: port,
105 > rp: rp,
106 > replicaPoints: replicaPoints,
107 > refreshChan: make(chan struct{}),
108 > shutdownCh: make(chan struct{}),
109 > logger: log.With(logger, tag.ComponentServiceResolver, tag.Service(service)),
110 > scheduledRefreshMap: make(map[int64]*time.Timer),
111 > listeners: make(map[string]chan<- *membership.ChangedEvent),
112 > }
113 > resolver.ringAndHosts.Store(ringAndHosts{
114 > ring: newHashRing(replicaPoints),
115 > hosts: make(map[string]*hostInfo),
116 > })
117 > return resolver
118 > }
119
120 > func newHashRing(replicaPoints int) *hashring.HashRing { service_resolver.go
121 > return hashring.New(farm.Fingerprint32, replicaPoints)
122 > }
123
124 // Start starts the oracle
125 > func (r *serviceResolver) Start() { service_resolver.go
126 > r.rp.AddListener(r)
127 > if err := r.refresh(refreshModeAlways); err != nil {
128 r.logger.Fatal("unable to start ring pop service resolver", tag.Error(err))
129 }
130
131 > r.shutdownWG.Add(1) service_resolver.go
132 > go r.refreshRingWorker()
133 }
134
135 // Stop stops the resolver
136 > func (r *serviceResolver) Stop() { service_resolver.go
137 > r.listenerLock.Lock()
138 > defer r.listenerLock.Unlock()
139 > r.rp.RemoveListener(r)
140 > r.ringAndHosts.Store(ringAndHosts{
141 > ring: newHashRing(r.replicaPoints),
142 > hosts: nil,
143 > })
144 > r.listeners = make(map[string]chan<- *membership.ChangedEvent)
145 > close(r.shutdownCh)
146 >
147 > if success := common.AwaitWaitGroup(&r.shutdownWG, time.Minute); !success {
148 r.logger.Warn("service resolver timed out on shutdown.")
149 }
150 }
151
152 > func (r *serviceResolver) RequestRefresh() { service_resolver.go
153 > select {
154 > case r.refreshChan <- struct{}{}: service_resolver.go
155 > default: service_resolver.go
156 }
157 }
158
159 // Lookup finds the host in the ring responsible for serving the given key
160 > func (r *serviceResolver) Lookup(key string) (membership.HostInfo, error) { service_resolver.go
161 > ring, hosts := r.ring()
162 > addr, found := ring.Lookup(key)
163 > if !found {
164 > r.RequestRefresh() service_resolver.go
165 > return nil, membership.ErrInsufficientHosts
166 > }
167 > return hosts[addr], nil service_resolver.go
168 }
169
170 > func (r *serviceResolver) LookupN(key string, n int) []membership.HostInfo { service_resolver.go
171 > if n <= 0 {
172 return nil
173 }
174 > ring, hosts := r.ring() service_resolver.go
175 > addrs := ring.LookupN(key, n)
176 > if len(addrs) == 0 {
177 > r.RequestRefresh() service_resolver.go
178 > return nil
179 > }
180 > return util.MapSlice(addrs, func(addr string) membership.HostInfo { return hosts[addr] }) service_resolver.go
181 }
182
184 name string,
185 notifyChannel chan<- *membership.ChangedEvent,
186 > ) error { service_resolver.go
187 > r.listenerLock.Lock()
188 > defer r.listenerLock.Unlock()
189 > _, ok := r.listeners[name]
190 > if ok {
191 return membership.ErrListenerAlreadyExist
192 }
193 > r.listeners[name] = notifyChannel service_resolver.go
194 > return nil
195 }
196
197 func (r *serviceResolver) RemoveListener(
198 name string,
199 > ) error { service_resolver.go
200 > r.listenerLock.Lock()
201 > defer r.listenerLock.Unlock()
202 > _, ok := r.listeners[name]
203 > if !ok {
204 return nil
205 }
206 > delete(r.listeners, name) service_resolver.go
207 > return nil
208 }
209
247 func (r *serviceResolver) HandleEvent(
248 event events.Event,
250 > // We only about membership.ChangeEvent. Normally ringpop converts membership.ChangeEvent
251 > // into events.RingChangedEvent when its internal hash ring changes, but since we construct
252 > // our own hash rings with filtering, we have to handle the lower-level event ourselves.
253 > if _, ok := event.(rpmembership.ChangeEvent); ok {
254 > r.logger.Debug("Received a ring changed event")
255 > // Note that we receive events asynchronously, possibly out of order.
256 > // We cannot rely on the content of the event, rather we load everything
257 > // from ringpop when we get a notification that something changed.
258 > if err := r.refresh(refreshModeAlways); err != nil {
259 r.logger.Error("error refreshing ring when receiving a ring changed event", tag.Error(err))
260 }
262 }
263
264 > func (r *serviceResolver) refresh(mode refreshMode) error { service_resolver.go
265 > var event *membership.ChangedEvent
266 > var err error
267 > defer func() {
268 > if event != nil {
269 > r.emitEvent(event)
270 > }
271 }()
272
273 > r.refreshLock.Lock() service_resolver.go
274 > defer r.refreshLock.Unlock()
275 >
276 > if mode == refreshModeLazy && r.lastRefreshTime.After(time.Now().UTC().Add(-minRefreshInternal)) {
277 > return nil // refreshed too recently service_resolver.go
278 > }
279
280 > event, err = r.refreshLocked() service_resolver.go
281 > return err
282 }
283
284 > func (r *serviceResolver) refreshLocked() (*membership.ChangedEvent, error) { service_resolver.go
285 > hosts, nextEvent, err := r.getReachableMembers()
286 > if err != nil {
287 return nil, err
288 }
289
290 // if we found an add/remove event, schedule another refresh right at that time
291 > r.scheduleRefresh(nextEvent) service_resolver.go
292 >
293 > newMembersMap, changedEvent := r.compareMembers(hosts)
294 > if changedEvent == nil {
295 > return nil, nil
296 > }
297
298 > ring := newHashRing(r.replicaPoints) service_resolver.go
299 > ring.AddMembers(util.MapSlice(hosts, func(h *hostInfo) rpmembership.Member { return h })...)
300
301 > r.lastRefreshTime = time.Now().UTC() service_resolver.go
302 > r.ringAndHosts.Store(ringAndHosts{
303 > ring: ring,
304 > hosts: newMembersMap,
305 > })
306 >
307 > addrs := util.MapSlice(hosts, func(h *hostInfo) string { return h.summary() })
308 > slices.Sort(addrs)
309 > r.logger.Info("Current reachable members", tag.Addresses(addrs))
310 >
311 > return changedEvent, nil
312 }
313
314 > func (r *serviceResolver) scheduleRefresh(nextEvent int64) { service_resolver.go
315 > if nextEvent == 0 {
316 > return
317 > }
318 if _, ok := r.scheduledRefreshMap[nextEvent]; ok {
319 return // already have a timer scheduled for this time
333 }
334
335 > func (r *serviceResolver) getReachableMembers() ([]*hostInfo, int64, error) { service_resolver.go
336 > members, err := r.rp.GetReachableMemberObjects(swim.MemberWithLabelAndValue(roleKey, string(r.service)))
337 > if err != nil {
338 return nil, 0, err
339 }
342 // need to keep track of one event since we'll refresh at that time and find the next one.
343 // Note that nextEvent is mutated by the filter functions below.
344 > nowUnix := time.Now().Unix() service_resolver.go
345 > nextEvent := int64(math.MaxInt64)
346 >
347 > // Filter by startAt
348 > members = slices.DeleteFunc(members, func(member swim.Member) bool {
349 > startAt, err := parseIntLabel(member, startAtKey)
350 > if err != nil {
351 > return false // ignore label if missing or can't parse
352 > } else if startAt <= nowUnix {
353 return false // start time is in the past
354 }
359
360 // Filter by stopAt
361 > members = slices.DeleteFunc(members, func(member swim.Member) bool { service_resolver.go
362 > stopAt, err := parseIntLabel(member, stopAtKey)
363 > if err != nil {
364 > return false // ignore label if missing or can't parse
365 > } else if stopAt > nowUnix {
366 // stop time is in the future: schedule refresh at that time
367 nextEvent = min(nextEvent, stopAt)
372
373 // Turn swim.Members into hostInfo
374 > hosts := make([]*hostInfo, len(members)) service_resolver.go
375 > for i, member := range members {
376 > servicePort := r.port
377 >
378 > // Each temporal service in the ring should advertise which port it has its gRPC listener
379 > // on via a service label. If we cannot find the label, we will assume that the
380 > // temporal service is listening on the same port that this node is listening on.
381 > servicePortLabel, ok := member.Label(portKey)
382 > if ok {
383 > servicePort, err = strconv.Atoi(servicePortLabel)
384 > if err != nil {
385 return nil, 0, err
386 }
389 }
390
391 > hostPort, err := replaceServicePort(member.Address, servicePort) service_resolver.go
392 > if err != nil {
393 return nil, 0, err
394 }
395
396 // We can share member.Labels without copying since we never modify it.
397 > hosts[i] = newHostInfo(hostPort, member.Labels) service_resolver.go
398 }
399
400 > if nextEvent == math.MaxInt64 { service_resolver.go
401 > nextEvent = 0
402 > }
403 > return hosts, nextEvent, nil
404 }
405
406 > func (r *serviceResolver) emitEvent(event *membership.ChangedEvent) { service_resolver.go
407 > // Notify listeners
408 > r.listenerLock.RLock()
409 > defer r.listenerLock.RUnlock()
410 >
411 > for name, ch := range r.listeners {
412 > select { service_resolver.go
413 > case ch <- event:
414 default:
415 r.logger.Error("Failed to send listener notification, channel full", tag.ListenerName(name))
418 }
419
420 > func (r *serviceResolver) refreshRingWorker() { service_resolver.go
421 > defer r.shutdownWG.Done()
422 >
423 > refreshTicker := time.NewTicker(defaultRefreshInterval)
424 > defer refreshTicker.Stop()
425 >
426 > for {
427 > select {
428 > case <-r.shutdownCh: service_resolver.go
429 > return
430 > case <-r.refreshChan: service_resolver.go
431 > if err := r.refresh(refreshModeLazy); err != nil {
432 r.logger.Error("error refreshing ring by request", tag.Error(err))
433 }
440 }
441
442 > func (r *serviceResolver) ring() (*hashring.HashRing, map[string]*hostInfo) { service_resolver.go
443 > ring := r.ringAndHosts.Load().(ringAndHosts)
444 > return ring.ring, ring.hosts
445 > }
446
447 > func (r *serviceResolver) compareMembers(hosts []*hostInfo) (map[string]*hostInfo, *membership.ChangedEvent) { service_resolver.go
448 > event := &membership.ChangedEvent{}
449 > changed := false
450 > _, prevHosts := r.ring() // note that this is always called with refreshLock so we can't miss an update here
451 > newMembersMap := make(map[string]*hostInfo, len(hosts))
452 > for _, host := range hosts {
453 > newMembersMap[host.GetAddress()] = host
454 > if prev, ok := prevHosts[host.GetAddress()]; !ok {
455 > event.HostsAdded = append(event.HostsAdded, host) service_resolver.go
456 > changed = true
457 > } else if prev.labelsChecksum != host.labelsChecksum { service_resolver.go
458 > event.HostsChanged = append(event.HostsChanged, host) service_resolver.go
459 > changed = true
460 > }
461 }
462 > for addr, prev := range prevHosts { service_resolver.go
463 > if _, ok := newMembersMap[addr]; !ok {
464 > event.HostsRemoved = append(event.HostsRemoved, prev) service_resolver.go
465 > changed = true
466 > }
467 }
468 > if changed { service_resolver.go
469 > return newMembersMap, event
470 > }
471 > return newMembersMap, nil service_resolver.go
472 }
473
474 // buildBroadcastHostPort return the listener hostport from an existing tchannel
475 // and overrides the address with broadcastAddress if specified
476 > func buildBroadcastHostPort(listenerPeerInfo tchannel.LocalPeerInfo, broadcastAddress string) (string, error) { service_resolver.go
477 > // Ephemeral port check copied from ringpop-go/ringpop.go/channelAddressResolver
478 > // Check that TChannel is listening on a real hostport. By default,
479 > // TChannel listens on an ephemeral host/port. The real port is then
480 > // assigned by the OS when ListenAndServe is called. If the hostport is
481 > // ephemeral, it means TChannel is not yet listening and the hostport
482 > // cannot be resolved.
483 > if listenerPeerInfo.IsEphemeralHostPort() {
484 return "", ringpop.ErrEphemeralAddress
485 }
486
487 // Parse listener hostport
488 > listenerIPString, port, err := net.SplitHostPort(listenerPeerInfo.HostPort) service_resolver.go
489 > if err != nil {
490 return "", err
491 }
492
493 // Broadcast IP override
494 > if broadcastAddress != "" { service_resolver.go
495 > // Parse supplied broadcastAddress override
496 > ip := net.ParseIP(broadcastAddress)
497 > if ip == nil {
498 return "", errors.New("broadcastAddress set but unknown failure encountered while parsing")
499 }
500
501 // If no errors, use the parsed IP with the port from our listener
502 > return net.JoinHostPort(ip.String(), port), nil service_resolver.go
503 }
504
516
517 // parseIntLabel returns the value of the given label as an integer.
518 > func parseIntLabel(member swim.Member, label string) (int64, error) { service_resolver.go
519 > str, ok := member.Label(label)
520 > if !ok {
521 > return 0, errMissingLabel
522 > }
523 return strconv.ParseInt(str, 10, 64)
524 }
go.temporal.io/server/common/membership/ringpop/monitor.go 212 covered LOC · 49 ranges

Open complete file

84 joinTime time.Time,
85 replicaPoints int,
86 > ) *monitor { monitor.go
87 > lifecycleCtx, lifecycleCancel := context.WithCancel(context.Background())
88 > lifecycleCtx = headers.SetCallerInfo(
89 > lifecycleCtx,
90 > headers.SystemBackgroundHighCallerInfo,
91 > )
92 > hostID, _ := uuid.New().MarshalBinary()
93 > // MarshalBinary should never error.
94 >
95 > rpo := &monitor{
96 > status: common.DaemonStatusInitialized,
97 >
98 > lifecycleCtx: lifecycleCtx,
99 > lifecycleCancel: lifecycleCancel,
100 >
101 > serviceName: serviceName,
102 > services: services,
103 > rp: rp,
104 > rings: make(map[primitives.ServiceName]*serviceResolver),
105 > replicaPoints: replicaPoints,
106 > logger: logger,
107 > metadataManager: metadataManager,
108 > broadcastHostPortResolver: broadcastHostPortResolver,
109 > hostID: hostID,
110 > initialized: future.NewFuture[struct{}](),
111 > maxJoinDuration: maxJoinDuration,
112 > propagationTime: propagationTime,
113 > joinTime: joinTime,
114 > }
115 > for service, port := range services {
116 > rpo.rings[service] = newServiceResolver(service, port, rp, replicaPoints, logger)
117 > }
118 > return rpo
119 }
120
122 // it's safe for Stop() to run, which is at any point when we are neither updating the status field nor
123 // starting rings
124 > func (rpo *monitor) Start() { monitor.go
125 > rpo.stateLock.Lock()
126 > if rpo.status != common.DaemonStatusInitialized {
127 rpo.stateLock.Unlock()
128 return
129 }
130 > rpo.status = common.DaemonStatusStarted monitor.go
131 > rpo.stateLock.Unlock()
132 >
133 > broadcastAddress, err := rpo.broadcastHostPortResolver()
134 > if err != nil {
135 rpo.logger.Fatal("unable to resolve broadcast address", tag.Error(err))
136 }
140 // we must know our seed nodes before bootstrapping
141
142 > if err = rpo.startHeartbeat(broadcastAddress); err != nil { monitor.go
143 rpo.logger.Fatal("unable to initialize membership heartbeats", tag.Error(err))
144 }
145
146 > if err = rpo.bootstrapRingPop(); err != nil { monitor.go
147 // Stop() called during Start()'s execution. This is ok
148 if strings.Contains(err.Error(), "destroyed while attempting to join") {
152 }
153
154 > labels, err := rpo.rp.Labels() monitor.go
155 > if err != nil {
156 rpo.logger.Fatal("unable to get ringpop labels", tag.Error(err))
157 }
158
159 > if until := time.Until(rpo.joinTime); until > 0 && until.Seconds() < maxScheduledEventTimeSeconds { monitor.go
160 if err = labels.Set(startAtKey, strconv.FormatInt(rpo.joinTime.Unix(), 10)); err != nil {
161 rpo.logger.Fatal("unable to set ringpop label", tag.Error(err), tag.Key(startAtKey))
168 }
169
170 > if err = labels.Set(portKey, strconv.Itoa(rpo.services[rpo.serviceName])); err != nil { monitor.go
171 rpo.logger.Fatal("unable to set ringpop label", tag.Error(err), tag.Key(portKey))
172 }
173
174 // This label should be set last, it's used as the prediciate for finding members for rings.
175 > if err = labels.Set(roleKey, string(rpo.serviceName)); err != nil { monitor.go
176 rpo.logger.Fatal("unable to set ringpop label", tag.Error(err), tag.Key(roleKey))
177 }
178
179 // Our individual rings may not support concurrent start/stop calls so we reacquire the state lock while acting upon them
180 > rpo.stateLock.Lock() monitor.go
181 > for _, ring := range rpo.rings {
182 > ring.Start()
183 > }
184 > rpo.stateLock.Unlock()
185 >
186 > rpo.initialized.Set(struct{}{}, nil)
187 }
188
189 // bootstrap ring pop service by discovering the bootstrap hosts and joining the ring pop cluster
190 > func (rpo *monitor) bootstrapRingPop() error { monitor.go
191 > policy := backoff.NewExponentialRetryPolicy(healthyHostLastHeartbeatCutoff / 2).
192 > WithBackoffCoefficient(1).
193 > WithMaximumAttempts(maxBootstrapRetries)
194 > op := func() error {
195 > hostPorts, err := rpo.fetchCurrentBootstrapHostports()
196 > if err != nil {
197 return err
198 }
199
200 > bootParams := &swim.BootstrapOptions{ monitor.go
201 > ParallelismFactor: 10,
202 > JoinSize: 1,
203 > MaxJoinDuration: rpo.maxJoinDuration,
204 > DiscoverProvider: statichosts.New(hostPorts...),
205 > }
206 >
207 > _, err = rpo.rp.Bootstrap(bootParams)
208 > if err != nil {
209 rpo.logger.Warn("unable to bootstrap ringpop. retrying", tag.Error(err))
210 }
211 > return err monitor.go
212 }
213
214 > if err := backoff.ThrottleRetry(op, policy, nil); err != nil { monitor.go
215 return fmt.Errorf("exhausted all retries: %w", err)
216 }
217 > return nil monitor.go
218 }
219
226 }
227
228 > func (rpo *monitor) WaitUntilInitialized(ctx context.Context) error { monitor.go
229 > _, err := rpo.initialized.Get(ctx)
230 > return err
231 > }
232
233 func (rpo *monitor) upsertMyMembership(
234 ctx context.Context,
235 request *persistence.UpsertClusterMembershipRequest,
236 > ) error { monitor.go
237 > err := rpo.metadataManager.UpsertClusterMembership(ctx, request)
238 >
239 > if err == nil {
240 > hostID, err := uuid.FromBytes(request.HostID)
241 > if err != nil {
242 return err
243 }
244 > rpo.logger.Debug("Membership heartbeat upserted successfully", monitor.go
245 > tag.Address(request.RPCAddress.String()),
246 > tag.Port(int(request.RPCPort)),
247 > tag.HostID(hostID.String()))
248 }
249
250 > return err monitor.go
251 }
252
253 // splitHostPortTyped expands upon net.SplitHostPort by providing type parsing.
254 > func splitHostPortTyped(hostPort string) (net.IP, uint16, error) { monitor.go
255 > ipstr, portstr, err := net.SplitHostPort(hostPort)
256 > if err != nil {
257 return nil, 0, err
258 }
259
260 > broadcastAddress := net.ParseIP(ipstr) monitor.go
261 > broadcastPort, err := strconv.ParseUint(portstr, 10, 16)
262 > if err != nil {
263 return nil, 0, err
264 }
265
266 > return broadcastAddress, uint16(broadcastPort), nil monitor.go
267 }
268
269 > func (rpo *monitor) startHeartbeat(broadcastHostport string) error { monitor.go
270 > // Start by cleaning up expired records to avoid growth
271 > err := rpo.metadataManager.PruneClusterMembership(rpo.lifecycleCtx, &persistence.PruneClusterMembershipRequest{MaxRecordsPruned: 10})
272 > if err != nil {
273 return err
274 }
275
276 > sessionStarted := time.Now().UTC() monitor.go
277 >
278 > // Parse and validate broadcast hostport
279 > broadcastAddress, broadcastPort, err := splitHostPortTyped(broadcastHostport)
280 > if err != nil {
281 return err
282 }
283
284 // Parse and validate existing service name
285 > role, err := serviceNameToServiceTypeEnum(rpo.serviceName) monitor.go
286 > if err != nil {
287 return err
288 }
289
290 > req := &persistence.UpsertClusterMembershipRequest{ monitor.go
291 > Role: role,
292 > RPCAddress: broadcastAddress,
293 > RPCPort: broadcastPort,
294 > SessionStart: sessionStarted,
295 > RecordExpiry: upsertMembershipRecordExpiryDefault,
296 > HostID: rpo.hostID,
297 > }
298 >
299 > // Upsert before fetching bootstrap hosts.
300 > // This makes us discoverable by other Temporal cluster members
301 > // Expire in 48 hours to allow for inspection of table by humans for debug scenarios.
302 > // For bootstrapping, we filter to a much shorter duration on the
303 > // read side by filtering on the last time a heartbeat was seen.
304 > err = rpo.upsertMyMembership(rpo.lifecycleCtx, req)
305 > if err == nil {
306 > hostID, err := uuid.FromBytes(rpo.hostID)
307 > if err != nil {
308 return err
309 }
310 > rpo.logger.Info("Membership heartbeat upserted successfully", monitor.go
311 > tag.Address(broadcastAddress.String()),
312 > tag.Port(int(broadcastPort)),
313 > tag.HostID(hostID.String()))
314 >
315 > rpo.startHeartbeatUpsertLoop(req)
316 }
317
318 > return err monitor.go
319 }
320
321 > func (rpo *monitor) fetchCurrentBootstrapHostports() ([]string, error) { monitor.go
322 > pageSize := 1000
323 > set := make(map[string]struct{})
324 >
325 > var nextPageToken []byte
326 >
327 > for {
328 > resp, err := rpo.metadataManager.GetClusterMembers(
329 > rpo.lifecycleCtx,
330 > &persistence.GetClusterMembersRequest{
331 > LastHeartbeatWithin: healthyHostLastHeartbeatCutoff,
332 > PageSize: pageSize,
333 > NextPageToken: nextPageToken,
334 > })
335 > if err != nil {
336 return nil, err
337 }
338
339 // Dedupe on hostport
340 > for _, host := range resp.ActiveMembers { monitor.go
341 > set[net.JoinHostPort(host.RPCAddress.String(), convert.Uint16ToString(host.RPCPort))] = struct{}{}
342 > }
343 > nextPageToken = resp.NextPageToken
344 >
345 > // Stop iterating once we have either 500 unique ip:port combos or there is no more results.
346 > if len(nextPageToken) == 0 || len(set) >= 500 {
347 > bootstrapHostPorts := make([]string, 0, len(set))
348 > for k := range set {
349 > bootstrapHostPorts = append(bootstrapHostPorts, k)
350 > }
351
352 > rpo.logger.Info("bootstrap hosts fetched", tag.BootstrapHostPorts(strings.Join(bootstrapHostPorts, ","))) monitor.go
353 > return bootstrapHostPorts, nil
354 }
355 }
356 }
357
358 > func (rpo *monitor) startHeartbeatUpsertLoop(request *persistence.UpsertClusterMembershipRequest) { monitor.go
359 > loopUpsertMembership := func() {
360 > for {
361 > select {
362 case <-rpo.lifecycleCtx.Done():
363 return
364 > default: monitor.go
365 }
366 > err := rpo.upsertMyMembership(rpo.lifecycleCtx, request) monitor.go
367 > if err != nil {
368 rpo.logger.Error("Membership upsert failed.", tag.Error(err))
369 }
370
371 > jitter := math.Round(rand.Float64() * 5) monitor.go
372 > time.Sleep(time.Second * time.Duration(10+jitter))
373 }
374 }
375
376 > go loopUpsertMembership() monitor.go
377 }
378
380 // for the entire call as the individual ring Start/Stop functions may not be safe to
381 // call concurrently
382 > func (rpo *monitor) Stop() { monitor.go
383 > rpo.stateLock.Lock()
384 > defer rpo.stateLock.Unlock()
385 > if rpo.status != common.DaemonStatusStarted {
386 return
387 }
388 > rpo.status = common.DaemonStatusStopped monitor.go
389 >
390 > rpo.lifecycleCancel()
391 >
392 > for _, ring := range rpo.rings {
393 > ring.Stop()
394 > }
395
396 > rpo.rp.Destroy() monitor.go
397 }
398
399 > func (rpo *monitor) EvictSelf() error { monitor.go
400 > return rpo.rp.SelfEvict()
401 > }
402
403 func (rpo *monitor) EvictSelfAt(asOf time.Time) (time.Duration, error) {
425 }
426
427 > func (rpo *monitor) GetResolver(service primitives.ServiceName) (membership.ServiceResolver, error) { monitor.go
428 > ring, found := rpo.rings[service]
429 > if !found {
430 return nil, membership.ErrUnknownService
431 }
432 > return ring, nil monitor.go
433 }
434
437 }
438
439 > func (rpo *monitor) SetDraining(draining bool) error { monitor.go
440 > labels, err := rpo.rp.Labels()
441 > if err != nil {
442 // This only happens if ringpop is not bootstrapped yet.
443 return err
444 }
445 > return labels.Set(drainingKey, strconv.FormatBool(draining)) monitor.go
446 }
447
450 }
451
452 > func replaceServicePort(address string, servicePort int) (string, error) { monitor.go
453 > host, _, err := net.SplitHostPort(address)
454 > if err != nil {
455 return "", membership.ErrIncorrectAddressFormat
456 }
457 > return net.JoinHostPort(host, convert.IntToString(servicePort)), nil monitor.go
458 }
459
463
464 // RegisterServiceNameToServiceTypeEnum must be called from a static init().
465 > func RegisterServiceNameToServiceTypeEnum(serviceName primitives.ServiceName, serviceType persistence.ServiceType) { monitor.go
466 > serviceNameToServiceTypeEnumMap[serviceName] = serviceType
467 > }
468
469 > func init() { monitor.go
470 > RegisterServiceNameToServiceTypeEnum(primitives.AllServices, persistence.All)
471 > RegisterServiceNameToServiceTypeEnum(primitives.FrontendService, persistence.Frontend)
472 > RegisterServiceNameToServiceTypeEnum(primitives.InternalFrontendService, persistence.InternalFrontend)
473 > RegisterServiceNameToServiceTypeEnum(primitives.HistoryService, persistence.History)
474 > RegisterServiceNameToServiceTypeEnum(primitives.MatchingService, persistence.Matching)
475 > RegisterServiceNameToServiceTypeEnum(primitives.WorkerService, persistence.Worker)
476 > }
477
478 > func serviceNameToServiceTypeEnum(name primitives.ServiceName) (persistence.ServiceType, error) { monitor.go
479 > if serviceType, ok := serviceNameToServiceTypeEnumMap[name]; ok {
480 > return serviceType, nil
481 > }
482
483 return persistence.All, fmt.Errorf("unable to parse servicename '%s'", name)
go.temporal.io/server/common/persistence/persistence_retryable_clients.go 202 covered LOC · 48 ranges

Open complete file

66 policy backoff.RetryPolicy,
67 isRetryable backoff.IsRetryable,
68 > ) ShardManager { persistence_retryable_clients.go
69 > return &shardRetryablePersistenceClient{
70 > persistence: persistence,
71 > policy: policy,
72 > isRetryable: isRetryable,
73 > }
74 > }
75
76 // NewExecutionPersistenceRetryableClient creates a client to manage executions
79 policy backoff.RetryPolicy,
80 isRetryable backoff.IsRetryable,
81 > ) ExecutionManager { persistence_retryable_clients.go
82 > return &executionRetryablePersistenceClient{
83 > persistence: persistence,
84 > policy: policy,
85 > isRetryable: isRetryable,
86 > }
87 > }
88
89 // NewTaskPersistenceRetryableClient creates a client to manage tasks
92 policy backoff.RetryPolicy,
93 isRetryable backoff.IsRetryable,
94 > ) TaskManager { persistence_retryable_clients.go
95 > return &taskRetryablePersistenceClient{
96 > persistence: persistence,
97 > policy: policy,
98 > isRetryable: isRetryable,
99 > }
100 > }
101
102 // NewMetadataPersistenceRetryableClient creates a MetadataManager client to manage metadata
105 policy backoff.RetryPolicy,
106 isRetryable backoff.IsRetryable,
107 > ) MetadataManager { persistence_retryable_clients.go
108 > return &metadataRetryablePersistenceClient{
109 > persistence: persistence,
110 > policy: policy,
111 > isRetryable: isRetryable,
112 > }
113 > }
114
115 // NewClusterMetadataPersistenceRetryableClient creates a ClusterMetadataManager client to manage cluster metadata
118 policy backoff.RetryPolicy,
119 isRetryable backoff.IsRetryable,
120 > ) ClusterMetadataManager { persistence_retryable_clients.go
121 > return &clusterMetadataRetryablePersistenceClient{
122 > persistence: persistence,
123 > policy: policy,
124 > isRetryable: isRetryable,
125 > }
126 > }
127
128 // NewQueuePersistenceRetryableClient creates a client to manage queue
131 policy backoff.RetryPolicy,
132 isRetryable backoff.IsRetryable,
134 > return &queueRetryablePersistenceClient{
135 > persistence: persistence,
136 > policy: policy,
137 > isRetryable: isRetryable,
138 > }
139 > }
140
141 // NewNexusEndpointPersistenceRetryableClient creates a NexusEndpointManager client to manage nexus endpoints
144 policy backoff.RetryPolicy,
145 isRetryable backoff.IsRetryable,
146 > ) NexusEndpointManager { persistence_retryable_clients.go
147 > return &nexusEndpointRetryablePersistenceClient{
148 > persistence: persistence,
149 > policy: policy,
150 > isRetryable: isRetryable,
151 > }
152 > }
153
154 func (p *shardRetryablePersistenceClient) GetName() string {
159 ctx context.Context,
160 request *GetOrCreateShardRequest,
161 > ) (*GetOrCreateShardResponse, error) { persistence_retryable_clients.go
162 > var response *GetOrCreateShardResponse
163 > op := func(ctx context.Context) error {
164 > var err error
165 > response, err = p.persistence.GetOrCreateShard(ctx, request)
166 > return err
167 > }
168
169 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
170 > return response, err
171 }
172
174 ctx context.Context,
175 request *UpdateShardRequest,
177 > op := func(ctx context.Context) error {
178 > return p.persistence.UpdateShard(ctx, request)
179 > }
180
181 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
182 }
183
185 ctx context.Context,
186 request *AssertShardOwnershipRequest,
188 > op := func(ctx context.Context) error {
189 > return p.persistence.AssertShardOwnership(ctx, request)
190 > }
191
192 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
193 }
194
195 > func (p *shardRetryablePersistenceClient) Close() { persistence_retryable_clients.go
196 > p.persistence.Close()
197 > }
198
199 > func (p *executionRetryablePersistenceClient) GetName() string { persistence_retryable_clients.go
200 > return p.persistence.GetName()
201 > }
202
203 func (p *executionRetryablePersistenceClient) GetHistoryBranchUtil() HistoryBranchUtil {
346 ctx context.Context,
347 request *GetHistoryTasksRequest,
348 > ) (*GetHistoryTasksResponse, error) { persistence_retryable_clients.go
349 > var response *GetHistoryTasksResponse
350 > op := func(ctx context.Context) error {
351 > var err error
352 > response, err = p.persistence.GetHistoryTasks(ctx, request)
353 > return err
354 > }
355
356 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
357 > return response, err
358 }
359
598 }
599
600 > func (p *executionRetryablePersistenceClient) Close() { persistence_retryable_clients.go
601 > p.persistence.Close()
602 > }
603
604 func (p *taskRetryablePersistenceClient) GetName() string {
788 }
789
790 > func (p *taskRetryablePersistenceClient) Close() { persistence_retryable_clients.go
791 > p.persistence.Close()
792 > }
793
794 func (p *metadataRetryablePersistenceClient) GetName() string {
814 ctx context.Context,
815 request *GetNamespaceRequest,
816 > ) (*GetNamespaceResponse, error) { persistence_retryable_clients.go
817 > var response *GetNamespaceResponse
818 > op := func(ctx context.Context) error {
819 > var err error
820 > response, err = p.persistence.GetNamespace(ctx, request)
821 > return err
822 > }
823
824 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
825 > return response, err
826 }
827
873 ctx context.Context,
874 request *ListNamespacesRequest,
875 > ) (*ListNamespacesResponse, error) { persistence_retryable_clients.go
876 > var response *ListNamespacesResponse
877 > op := func(ctx context.Context) error {
878 > var err error
879 > response, err = p.persistence.ListNamespaces(ctx, request)
880 > return err
881 > }
882
883 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
884 > return response, err
885 }
886
902 ctx context.Context,
903 currentClusterName string,
905 > op := func(ctx context.Context) error {
906 > return p.persistence.InitializeSystemNamespaces(ctx, currentClusterName)
907 > }
908
909 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
910 }
911
912 func (p *metadataRetryablePersistenceClient) WatchNamespaces(
913 ctx context.Context,
914 > ) (<-chan *NamespaceWatchEvent, error) { persistence_retryable_clients.go
915 > var watchCh <-chan *NamespaceWatchEvent
916 > op := func(ctx context.Context) error {
917 > var err error
918 > watchCh, err = p.persistence.WatchNamespaces(ctx)
919 > return err
920 > }
921
922 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
923 > return watchCh, err
924 }
925
926 > func (p *metadataRetryablePersistenceClient) Close() { persistence_retryable_clients.go
927 > p.persistence.Close()
928 > }
929
930 func (p *clusterMetadataRetryablePersistenceClient) GetName() string {
935 ctx context.Context,
936 request *GetClusterMembersRequest,
937 > ) (*GetClusterMembersResponse, error) { persistence_retryable_clients.go
938 > var response *GetClusterMembersResponse
939 > op := func(ctx context.Context) error {
940 > var err error
941 > response, err = p.persistence.GetClusterMembers(ctx, request)
942 > return err
943 > }
944
945 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
946 > return response, err
947 }
948
950 ctx context.Context,
951 request *UpsertClusterMembershipRequest,
953 > op := func(ctx context.Context) error {
954 > return p.persistence.UpsertClusterMembership(ctx, request)
955 > }
956
957 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
958 }
959
961 ctx context.Context,
962 request *PruneClusterMembershipRequest,
964 > op := func(ctx context.Context) error {
965 > return p.persistence.PruneClusterMembership(ctx, request)
966 > }
967
968 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
969 }
970
972 ctx context.Context,
973 request *ListClusterMetadataRequest,
974 > ) (*ListClusterMetadataResponse, error) { persistence_retryable_clients.go
975 > var response *ListClusterMetadataResponse
976 > op := func(ctx context.Context) error {
977 > var err error
978 > response, err = p.persistence.ListClusterMetadata(ctx, request)
979 > return err
980 > }
981
982 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
983 > return response, err
984 }
985
986 func (p *clusterMetadataRetryablePersistenceClient) GetCurrentClusterMetadata(
987 ctx context.Context,
988 > ) (*GetClusterMetadataResponse, error) { persistence_retryable_clients.go
989 > var response *GetClusterMetadataResponse
990 > op := func(ctx context.Context) error {
991 > var err error
992 > response, err = p.persistence.GetCurrentClusterMetadata(ctx)
993 > return err
994 > }
995
996 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
997 > return response, err
998 }
999
1001 ctx context.Context,
1002 request *GetClusterMetadataRequest,
1003 > ) (*GetClusterMetadataResponse, error) { persistence_retryable_clients.go
1004 > var response *GetClusterMetadataResponse
1005 > op := func(ctx context.Context) error {
1006 > var err error
1007 > response, err = p.persistence.GetClusterMetadata(ctx, request)
1008 > return err
1009 > }
1010
1011 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
1012 > return response, err
1013 }
1014
1016 ctx context.Context,
1017 request *SaveClusterMetadataRequest,
1018 > ) (bool, error) { persistence_retryable_clients.go
1019 > var response bool
1020 > op := func(ctx context.Context) error {
1021 > var err error
1022 > response, err = p.persistence.SaveClusterMetadata(ctx, request)
1023 > return err
1024 > }
1025
1026 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
1027 > return response, err
1028 }
1029
1039 }
1040
1041 > func (p *clusterMetadataRetryablePersistenceClient) Close() { persistence_retryable_clients.go
1042 > p.persistence.Close()
1043 > }
1044
1045 func (p *queueRetryablePersistenceClient) Init(
1046 ctx context.Context,
1047 blob *commonpb.DataBlob,
1049 > op := func(ctx context.Context) error {
1050 > return p.persistence.Init(ctx, blob)
1051 > }
1052
1053 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
1054 }
1055
1198 }
1199
1200 > func (p *queueRetryablePersistenceClient) Close() { persistence_retryable_clients.go
1201 > p.persistence.Close()
1202 > }
1203
1204 func (p *nexusEndpointRetryablePersistenceClient) GetName() string {
1206 }
1207
1208 > func (p *nexusEndpointRetryablePersistenceClient) Close() { persistence_retryable_clients.go
1209 > p.persistence.Close()
1210 > }
1211
1212 func (p *nexusEndpointRetryablePersistenceClient) GetNexusEndpoint(
1227 ctx context.Context,
1228 request *ListNexusEndpointsRequest,
1229 > ) (*ListNexusEndpointsResponse, error) { persistence_retryable_clients.go
1230 > var response *ListNexusEndpointsResponse
1231 > op := func(ctx context.Context) error {
1232 > var err error
1233 > response, err = p.persistence.ListNexusEndpoints(ctx, request)
1234 > return err
1235 > }
1236 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable)
1237 > return response, err
1238 }
1239
go.temporal.io/server/service/worker/service.go 196 covered LOC · 16 ranges

Open complete file

134 grpcListener net.Listener,
135 healthServer *health.Server,
136 > ) (*Service, error) { service.go
137 > workerServiceResolver, err := membershipMonitor.GetResolver(primitives.WorkerService)
138 > if err != nil {
139 return nil, err
140 }
141
142 > s := &Service{ service.go
143 > config: serviceConfig,
144 > sdkClientFactory: sdkClientFactory,
145 > logger: logger,
146 > clusterMetadata: clusterMetadata,
147 > clientBean: clientBean,
148 > clusterMetadataManager: clusterMetadataManager,
149 > namespaceRegistry: namespaceRegistry,
150 > executionManager: executionManager,
151 > workerServiceResolver: workerServiceResolver,
152 > membershipMonitor: membershipMonitor,
153 > hostInfo: hostInfoProvider.HostInfo(),
154 > namespaceReplicationQueue: namespaceReplicationQueue,
155 > metricsHandler: metricsHandler,
156 > metadataManager: metadataManager,
157 > taskManager: taskManager,
158 > historyClient: historyClient,
159 > visibilityManager: visibilityManager,
160 >
161 > workerManager: workerManager,
162 > perNamespaceWorkerManager: perNamespaceWorkerManager,
163 > matchingClient: matchingClient,
164 > namespaceReplicationTaskExecutor: namespaceReplicationTaskExecutor,
165 >
166 > server: server,
167 > grpcListener: grpcListener,
168 > healthServer: healthServer,
169 > }
170 > if err := s.initScanner(serializer); err != nil {
171 return nil, err
172 }
173 > return s, nil service.go
174 }
175
183 dc *dynamicconfig.Collection,
184 persistenceConfig *config.Persistence,
185 > ) *Config { service.go
186 > config := &Config{
187 > ParentCloseCfg: &parentclosepolicy.Config{
188 > MaxConcurrentActivityExecutionSize: dynamicconfig.WorkerParentCloseMaxConcurrentActivityExecutionSize.Get(dc),
189 > MaxConcurrentWorkflowTaskExecutionSize: dynamicconfig.WorkerParentCloseMaxConcurrentWorkflowTaskExecutionSize.Get(dc),
190 > MaxConcurrentActivityTaskPollers: dynamicconfig.WorkerParentCloseMaxConcurrentActivityTaskPollers.Get(dc),
191 > MaxConcurrentWorkflowTaskPollers: dynamicconfig.WorkerParentCloseMaxConcurrentWorkflowTaskPollers.Get(dc),
192 > NumParentClosePolicySystemWorkflows: dynamicconfig.NumParentClosePolicySystemWorkflows.Get(dc),
193 > },
194 > ScannerCfg: &scanner.Config{
195 > MaxConcurrentActivityExecutionSize: dynamicconfig.WorkerScannerMaxConcurrentActivityExecutionSize.Get(dc),
196 > MaxConcurrentWorkflowTaskExecutionSize: dynamicconfig.WorkerScannerMaxConcurrentWorkflowTaskExecutionSize.Get(dc),
197 > MaxConcurrentActivityTaskPollers: dynamicconfig.WorkerScannerMaxConcurrentActivityTaskPollers.Get(dc),
198 > MaxConcurrentWorkflowTaskPollers: dynamicconfig.WorkerScannerMaxConcurrentWorkflowTaskPollers.Get(dc),
199 >
200 > PersistenceMaxQPS: dynamicconfig.ScannerPersistenceMaxQPS.Get(dc),
201 > Persistence: persistenceConfig,
202 > TaskQueueScannerEnabled: dynamicconfig.TaskQueueScannerEnabled.Get(dc),
203 > BuildIdScavengerEnabled: dynamicconfig.BuildIdScavengerEnabled.Get(dc),
204 > HistoryScannerEnabled: dynamicconfig.HistoryScannerEnabled.Get(dc),
205 > ExecutionsScannerEnabled: dynamicconfig.ExecutionsScannerEnabled.Get(dc),
206 > HistoryScannerDataMinAge: dynamicconfig.HistoryScannerDataMinAge.Get(dc),
207 > HistoryScannerVerifyRetention: dynamicconfig.HistoryScannerVerifyRetention.Get(dc),
208 > ExecutionScannerPerHostQPS: dynamicconfig.ExecutionScannerPerHostQPS.Get(dc),
209 > ExecutionScannerPerShardQPS: dynamicconfig.ExecutionScannerPerShardQPS.Get(dc),
210 > ExecutionDataDurationBuffer: dynamicconfig.ExecutionDataDurationBuffer.Get(dc),
211 > ExecutionScannerWorkerCount: dynamicconfig.ExecutionScannerWorkerCount.Get(dc),
212 > ExecutionScannerHistoryEventIdValidator: dynamicconfig.ExecutionScannerHistoryEventIdValidator.Get(dc),
213 > RemovableBuildIdDurationSinceDefault: dynamicconfig.RemovableBuildIdDurationSinceDefault.Get(dc),
214 > BuildIdScavengerVisibilityRPS: dynamicconfig.BuildIdScavengerVisibilityRPS.Get(dc),
215 >
216 > ScheduleInvariantsScannerOptions: dynamicconfig.ScheduleInvariantsScannerOptions.Get(dc),
217 > },
218 > BatcherRPS: dynamicconfig.BatcherRPS.Get(dc),
219 > BatcherConcurrency: dynamicconfig.BatcherConcurrency.Get(dc),
220 > EnableParentClosePolicyWorker: dynamicconfig.EnableParentClosePolicyWorker.Get(dc),
221 > PerNamespaceWorkerCount: dynamicconfig.WorkerPerNamespaceWorkerCount.Subscribe(dc),
222 > PerNamespaceWorkerOptions: dynamicconfig.WorkerPerNamespaceWorkerOptions.Subscribe(dc),
223 > PerNamespaceWorkerStartRate: dynamicconfig.WorkerPerNamespaceWorkerStartRate.Get(dc),
224 > ThrottledLogRPS: dynamicconfig.WorkerThrottledLogRPS.Get(dc),
225 > PersistenceMaxQPS: dynamicconfig.WorkerPersistenceMaxQPS.Get(dc),
226 > PersistenceGlobalMaxQPS: dynamicconfig.WorkerPersistenceGlobalMaxQPS.Get(dc),
227 > PersistenceNamespaceMaxQPS: dynamicconfig.WorkerPersistenceNamespaceMaxQPS.Get(dc),
228 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.WorkerPersistenceGlobalNamespaceMaxQPS.Get(dc),
229 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.DefaultPerShardNamespaceRPSMax,
230 > PersistenceDynamicRateLimitingParams: dynamicconfig.WorkerPersistenceDynamicRateLimitingParams.Get(dc),
231 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
232 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
233 >
234 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
235 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
236 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
237 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
238 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
239 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
240 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
241 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
242 > }
243 > return config
244 > }
245
246 // Start is called to start the service
247 > func (s *Service) Start() { service.go
248 > s.logger.Info(
249 > "worker starting",
250 > tag.ComponentWorker,
251 > )
252 >
253 > metrics.RestartCount.With(s.metricsHandler).Record(1)
254 >
255 > s.membershipMonitor.Start()
256 >
257 > s.ensureSystemNamespaceExists(context.TODO())
258 > s.startScanner()
259 >
260 > if s.clusterMetadata.IsGlobalNamespaceEnabled() {
261 s.startReplicator()
262 }
263 > if s.config.EnableParentClosePolicyWorker() { service.go
264 > s.startParentClosePolicyProcessor()
265 > }
266
267 > s.workerManager.Start() service.go
268 > s.perNamespaceWorkerManager.Start(
269 > // TODO: get these from fx instead of passing through Start
270 > s.hostInfo,
271 > s.workerServiceResolver,
272 > )
273 >
274 > healthpb.RegisterHealthServer(s.server, s.healthServer)
275 > s.healthServer.SetServingStatus(ServiceName, healthpb.HealthCheckResponse_SERVING)
276 >
277 > reflection.Register(s.server)
278 >
279 > go func() {
280 > s.logger.Info("Starting to serve on worker listener")
281 > if err := s.server.Serve(s.grpcListener); err != nil {
282 s.logger.Fatal("Failed to serve on worker listener", tag.Error(err))
283 }
284 }()
285
286 > s.logger.Info( service.go
287 > "worker service started",
288 > tag.ComponentWorker,
289 > tag.Address(s.hostInfo.GetAddress()),
290 > )
291 }
292
293 // Stop is called to stop the service
294 > func (s *Service) Stop() { service.go
295 > s.healthServer.SetServingStatus(ServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
296 >
297 > s.scanner.Stop()
298 > s.perNamespaceWorkerManager.Stop()
299 > s.workerManager.Stop()
300 > s.visibilityManager.Close()
301 >
302 > s.server.GracefulStop()
303 >
304 > s.logger.Info(
305 > "worker service stopped",
306 > tag.ComponentWorker,
307 > tag.Address(s.hostInfo.GetAddress()),
308 > )
309 > }
310
311 > func (s *Service) startParentClosePolicyProcessor() { service.go
312 > params := &parentclosepolicy.BootstrapParams{
313 > Config: *s.config.ParentCloseCfg,
314 > SdkClientFactory: s.sdkClientFactory,
315 > MetricsHandler: s.metricsHandler,
316 > Logger: s.logger,
317 > ClientBean: s.clientBean,
318 > CurrentCluster: s.clusterMetadata.GetCurrentClusterName(),
319 > HostInfo: s.hostInfo,
320 > }
321 > processor := parentclosepolicy.New(params)
322 > if err := processor.Start(); err != nil {
323 > s.logger.Fatal( service.go
324 > "error starting parentclosepolicy processor",
325 > tag.Error(err),
326 > )
327 > }
328 }
329
330 > func (s *Service) initScanner(serializer serialization.Serializer) error { service.go
331 > currentCluster := s.clusterMetadata.GetCurrentClusterName()
332 > adminClient, err := s.clientBean.GetRemoteAdminClient(currentCluster)
333 > if err != nil {
334 return err
335 }
336 > s.scanner = scanner.New( service.go
337 > s.logger,
338 > s.config.ScannerCfg,
339 > s.sdkClientFactory,
340 > s.metricsHandler,
341 > s.executionManager,
342 > s.metadataManager,
343 > s.visibilityManager,
344 > s.taskManager,
345 > s.historyClient,
346 > adminClient,
347 > s.matchingClient,
348 > s.namespaceRegistry,
349 > currentCluster,
350 > s.hostInfo,
351 > serializer,
352 > )
353 > return nil
354 }
355
356 > func (s *Service) startScanner() { service.go
357 > if err := s.scanner.Start(); err != nil {
358 > s.logger.Fatal( service.go
359 > "error starting scanner",
360 > tag.Error(err),
361 > )
362 > }
363 }
364
384 func (s *Service) ensureSystemNamespaceExists(
385 ctx context.Context,
386 > ) { service.go
387 > _, err := s.metadataManager.GetNamespace(ctx, &persistence.GetNamespaceRequest{Name: primitives.SystemLocalNamespace})
388 > switch err.(type) {
389 > case nil:
390 // noop
391 case *serviceerror.NamespaceNotFound:
go.temporal.io/server/common/cluster/metadata.go 187 covered LOC · 52 ranges

Open complete file

142 refreshDuration dynamicconfig.DurationPropertyFn,
143 logger log.Logger,
144 > ) Metadata { metadata.go
145 > if len(clusterInfo) == 0 {
146 panic("Empty cluster information")
147 > } else if len(masterClusterName) == 0 { metadata.go
148 panic("Master cluster name is empty")
149 > } else if len(currentClusterName) == 0 { metadata.go
150 panic("Current cluster name is empty")
151 > } else if failoverVersionIncrement == 0 || failoverVersionIncrement > math.MaxInt32 { metadata.go
152 panic("Version increment <= 0 or > 2147483647")
153 }
154
155 > versionToClusterName, err := updateVersionToClusterName(clusterInfo, failoverVersionIncrement) metadata.go
156 > if err != nil {
157 // nolint:forbidigo // matches the other startup-config panics in this constructor
158 panic(err.Error())
159 }
160 > if _, ok := clusterInfo[currentClusterName]; !ok { metadata.go
161 panic("Current cluster is not specified in cluster info")
162 }
163 > if _, ok := clusterInfo[masterClusterName]; !ok { metadata.go
164 panic("Master cluster is not specified in cluster info")
165 }
166
167 > copyClusterInfo := make(map[string]ClusterInformation) metadata.go
168 > maps.Copy(copyClusterInfo, clusterInfo)
169 > if refreshDuration == nil {
170 refreshDuration = dynamicconfig.GetDurationPropertyFn(refreshInterval)
171 }
172 > return &metadataImpl{ metadata.go
173 > status: common.DaemonStatusInitialized,
174 > enableGlobalNamespace: enableGlobalNamespace,
175 > failoverVersionIncrement: failoverVersionIncrement,
176 > masterClusterName: masterClusterName,
177 > currentClusterName: currentClusterName,
178 > clusterInfo: copyClusterInfo,
179 > versionToClusterName: versionToClusterName,
180 > clusterChangeCallback: make(map[any]CallbackFn),
181 > clusterMetadataStore: clusterMetadataStore,
182 > logger: logger,
183 > refreshDuration: refreshDuration,
184 > }
185 }
186
190 dynamicCollection *dynamicconfig.Collection,
191 logger log.Logger,
192 > ) Metadata { metadata.go
193 > return NewMetadata(
194 > config.EnableGlobalNamespace,
195 > config.FailoverVersionIncrement,
196 > config.MasterClusterName,
197 > config.CurrentClusterName,
198 > config.ClusterInformation,
199 > clusterMetadataStore,
200 > dynamicconfig.ClusterMetadataRefreshInterval.Get(dynamicCollection),
201 > logger,
202 > )
203 > }
204
205 > func (m *metadataImpl) Start() { metadata.go
206 > if !atomic.CompareAndSwapInt32(&m.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
207 return
208 }
209
210 // TODO: specify a timeout for the context
211 > ctx := headers.SetCallerInfo( metadata.go
212 > context.TODO(),
213 > headers.SystemBackgroundHighCallerInfo,
214 > )
215 > err := m.refreshClusterMetadata(ctx)
216 > if err != nil {
217 // Crash rather than start with partial cluster metadata (e.g. an invalid
218 // or missing row in cluster_metadata): replication and failover routing
221 m.logger.Fatal("Unable to initialize cluster metadata cache", tag.Error(err))
222 }
223 > m.refresher = goro.NewHandle(ctx).Go(m.refreshLoop) metadata.go
224 }
225
226 > func (m *metadataImpl) Stop() { metadata.go
227 > if !atomic.CompareAndSwapInt32(&m.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
228 return
229 }
230
231 > m.refresher.Cancel() metadata.go
232 > <-m.refresher.Done()
233 }
234
235 > func (m *metadataImpl) GetPingChecks() []pingable.Check { metadata.go
236 > return []pingable.Check{
237 > {
238 > Name: "cluster metadata lock",
239 > // we don't do any persistence ops under clusterLock, use a short timeout
240 > Timeout: 10 * time.Second,
241 > Ping: func() []pingable.Pingable {
242 > m.clusterLock.Lock()
243 > // nolint:staticcheck
244 > m.clusterLock.Unlock()
245 > return nil
246 > },
247 MetricsName: metrics.DDClusterMetadataLockLatency.Name(),
248 },
252 // not persistence ops.
253 Timeout: 10 * time.Second,
254 > Ping: func() []pingable.Pingable { metadata.go
255 > m.clusterCallbackLock.Lock()
256 > // nolint:staticcheck
257 > m.clusterCallbackLock.Unlock()
258 > return nil
259 > },
260 MetricsName: metrics.DDClusterMetadataCallbackLockLatency.Name(),
261 },
263 }
264
265 > func (m *metadataImpl) IsGlobalNamespaceEnabled() bool { metadata.go
266 > return m.enableGlobalNamespace
267 > }
268
269 func (m *metadataImpl) IsMasterCluster() bool {
271 }
272
273 > func (m *metadataImpl) GetClusterID() int64 { metadata.go
274 > m.clusterLock.RLock()
275 > defer m.clusterLock.RUnlock()
276 >
277 > info, ok := m.clusterInfo[m.currentClusterName]
278 > if !ok {
279 panic(fmt.Sprintf(
280 "Unknown cluster name: %v with given cluster initial failover version map: %v.",
283 ))
284 }
285 > return info.InitialFailoverVersion metadata.go
286 }
287
313 }
314
315 > func (m *metadataImpl) GetCurrentClusterName() string { metadata.go
316 > return m.currentClusterName
317 > }
318
319 > func (m *metadataImpl) GetAllClusterInfo() map[string]ClusterInformation { metadata.go
320 > m.clusterLock.RLock()
321 > defer m.clusterLock.RUnlock()
322 >
323 > result := make(map[string]ClusterInformation, len(m.clusterInfo))
324 > maps.Copy(result, m.clusterInfo)
325 > return result
326 > }
327
328 func (m *metadataImpl) ClusterNameForFailoverVersion(isGlobalNamespace bool, failoverVersion int64) string {
369 }
370
371 > func (m *metadataImpl) RegisterMetadataChangeCallback(callbackId any, cb CallbackFn) { metadata.go
372 > m.clusterCallbackLock.Lock()
373 > m.clusterChangeCallback[callbackId] = cb
374 > m.clusterCallbackLock.Unlock()
375 >
376 > oldEntries := make(map[string]*ClusterInformation)
377 > newEntries := make(map[string]*ClusterInformation)
378 > m.clusterLock.RLock()
379 > for clusterName, clusterInfo := range m.clusterInfo {
380 > oldEntries[clusterName] = nil
381 > newEntries[clusterName] = ShallowCopyClusterInformation(&clusterInfo)
382 > }
383 > m.clusterLock.RUnlock()
384 > cb(oldEntries, newEntries)
385 }
386
387 > func (m *metadataImpl) UnRegisterMetadataChangeCallback(callbackId any) { metadata.go
388 > m.clusterCallbackLock.Lock()
389 > delete(m.clusterChangeCallback, callbackId)
390 > m.clusterCallbackLock.Unlock()
391 > }
392
393 > func (m *metadataImpl) refreshLoop(ctx context.Context) error { metadata.go
394 > timer := time.NewTicker(m.refreshDuration())
395 > defer timer.Stop()
396 >
397 > for {
398 > select {
399 > case <-ctx.Done(): metadata.go
400 > return nil
401 case <-timer.C:
402 for err := m.refreshClusterMetadata(ctx); err != nil; err = m.refreshClusterMetadata(ctx) {
415 }
416
417 > func (m *metadataImpl) refreshClusterMetadata(ctx context.Context) error { metadata.go
418 > clusterMetadataMap, err := m.listAllClusterMetadataFromDB(ctx)
419 > if err != nil {
420 return err
421 }
422
423 > oldEntries := make(map[string]*ClusterInformation) metadata.go
424 > newEntries := make(map[string]*ClusterInformation)
425 >
426 > clusterInfoMap := m.GetAllClusterInfo()
427 > for clusterName, newClusterInfo := range clusterMetadataMap {
428 > oldClusterInfo, ok := clusterInfoMap[clusterName]
429 > if !ok {
430 // handle new cluster registry
431 oldEntries[clusterName] = nil
432 newEntries[clusterName] = ShallowCopyClusterInformation(newClusterInfo)
433 > } else if newClusterInfo.version > oldClusterInfo.version { metadata.go
434 if newClusterInfo.Enabled == oldClusterInfo.Enabled &&
435 newClusterInfo.ReplicationEnabled == oldClusterInfo.ReplicationEnabled &&
447 }
448 }
449 > for clusterName, oldClusterInfo := range clusterInfoMap { metadata.go
450 > if _, ok := clusterMetadataMap[clusterName]; !ok {
451 // removed cluster registry
452 oldEntries[clusterName] = &oldClusterInfo
455 }
456
457 > if len(oldEntries) > 0 { metadata.go
458 // Build a candidate map, validate it, and only commit on success.
459 // A bad row in cluster_metadata must not be able to crash the refresher
502 info ClusterInformation,
503 failoverVersionIncrement int64,
504 > ) error { metadata.go
505 > if clusterName == "" {
506 return errors.New("cluster name must not be empty")
507 }
508 > if info.InitialFailoverVersion <= 0 { metadata.go
509 return fmt.Errorf("cluster %q: InitialFailoverVersion must be > 0, got %d",
510 clusterName, info.InitialFailoverVersion)
511 }
512 > if info.InitialFailoverVersion >= failoverVersionIncrement { metadata.go
513 return fmt.Errorf("cluster %q: InitialFailoverVersion (%d) must be < FailoverVersionIncrement (%d)",
514 clusterName, info.InitialFailoverVersion, failoverVersionIncrement)
515 }
516 > if info.Enabled && info.RPCAddress == "" { metadata.go
517 return fmt.Errorf("cluster %q: RPCAddress must not be empty when Enabled=true", clusterName)
518 }
519 > return nil metadata.go
520 }
521
522 > func updateVersionToClusterName(clusterInfo map[string]ClusterInformation, failoverVersionIncrement int64) (map[int64]string, error) { metadata.go
523 > versionToClusterName := make(map[int64]string)
524 > for clusterName, info := range clusterInfo {
525 > if err := ValidateClusterInformation(clusterName, info, failoverVersionIncrement); err != nil {
526 return nil, err
527 }
528 > if existing, dup := versionToClusterName[info.InitialFailoverVersion]; dup { metadata.go
529 return nil, fmt.Errorf(
530 "duplicate InitialFailoverVersion %d for clusters %q and %q",
531 info.InitialFailoverVersion, existing, clusterName)
532 }
533 > versionToClusterName[info.InitialFailoverVersion] = clusterName metadata.go
534 }
535 > return versionToClusterName, nil metadata.go
536 }
537
538 func (m *metadataImpl) listAllClusterMetadataFromDB(
539 ctx context.Context,
540 > ) (map[string]*ClusterInformation, error) { metadata.go
541 > result := make(map[string]*ClusterInformation)
542 > metadataStore := m.clusterMetadataStore
543 > if metadataStore == nil {
544 return result, nil
545 }
546
547 > iterator := GetAllClustersIter(ctx, metadataStore) metadata.go
548 > for iterator.HasNext() {
549 > item, err := iterator.Next()
550 > if err != nil {
551 return nil, err
552 }
553 > result[item.GetClusterName()] = ClusterInformationFromDB(item) metadata.go
554 }
555 > return result, nil metadata.go
556 }
557
560 ctx context.Context,
561 metadataStore persistence.ClusterMetadataManager,
562 > ) collection.Iterator[*persistence.GetClusterMetadataResponse] { metadata.go
563 > paginationFn := func(paginationToken []byte) ([]*persistence.GetClusterMetadataResponse, []byte, error) {
564 > resp, err := metadataStore.ListClusterMetadata(
565 > ctx,
566 > &persistence.ListClusterMetadataRequest{
567 > PageSize: defaultClusterMetadataPageSize,
568 > NextPageToken: paginationToken,
569 > },
570 > )
571 > if err != nil {
572 return nil, nil, err
573 }
574 > return resp.ClusterMetadata, resp.NextPageToken, nil metadata.go
575 }
576
577 > iterator := collection.NewPagingIterator(paginationFn) metadata.go
578 > return iterator
579 }
580
581 > func ClusterInformationFromDB(getClusterResp *persistence.GetClusterMetadataResponse) *ClusterInformation { metadata.go
582 > return &ClusterInformation{
583 > Enabled: getClusterResp.GetIsConnectionEnabled(),
584 > InitialFailoverVersion: getClusterResp.GetInitialFailoverVersion(),
585 > RPCAddress: getClusterResp.GetClusterAddress(),
586 > HTTPAddress: getClusterResp.GetHttpAddress(),
587 > ClusterID: getClusterResp.GetClusterId(),
588 > ShardCount: getClusterResp.GetHistoryShardCount(),
589 > Tags: getClusterResp.GetTags(),
590 > ReplicationEnabled: getClusterResp.GetIsReplicationEnabled(),
591 > version: getClusterResp.Version,
592 > }
593 > }
594
595 // ShallowCopyClusterInformation returns a shallow copy of the given ClusterInformation. The [ClusterInformation.Tags]
596 // field is not deep-copied, so you must be careful when modifying it.
597 > func ShallowCopyClusterInformation(information *ClusterInformation) *ClusterInformation { metadata.go
598 > tmp := *information
599 > return &tmp
600 > }
601
602 // IsReplicationEnabledForCluster checks if replication is enabled for a cluster, considering the feature flag.
603 // When enableSeparateReplicationFlag is false, it falls back to only checking the Enabled flag.
604 // This is a shared helper function used across history service components.
605 > func IsReplicationEnabledForCluster(clusterInfo ClusterInformation, enableSeparateReplicationFlag bool) bool { metadata.go
606 > if enableSeparateReplicationFlag {
607 // New behavior: check both Enabled (for connectivity) and ReplicationEnabled (for replication streams)
608 return clusterInfo.Enabled && clusterInfo.ReplicationEnabled
609 }
610 // Old behavior: only check Enabled flag
611 > return clusterInfo.Enabled metadata.go
612 }
go.temporal.io/server/temporaltest/internal/lite_server.go 180 covered LOC · 26 ranges

Open complete file

72 }
73
74 > func (cfg *LiteServerConfig) apply(serverConfig *config.Config) { lite_server.go
75 > sqliteConfig := config.SQL{
76 > PluginName: sqliteplugin.PluginName,
77 > ConnectAttributes: make(map[string]string),
78 > DatabaseName: cfg.DatabaseFilePath,
79 > }
80 > if cfg.Ephemeral {
81 > sqliteConfig.ConnectAttributes["mode"] = "memory"
82 > sqliteConfig.ConnectAttributes["cache"] = "shared"
83 > // TODO(jlegrone): investigate whether a randomized db name is necessary when running in shared cache mode:
84 > // https://www.sqlite.org/sharedcache.html
85 > sqliteConfig.DatabaseName = fmt.Sprintf("%d", rand.Intn(9999999))
86 > } else {
87 sqliteConfig.ConnectAttributes["mode"] = "rwc"
88 }
89
90 > for k, v := range cfg.SQLitePragmas { lite_server.go
91 sqliteConfig.ConnectAttributes["_"+k] = v
92 }
93
94 > if cfg.FrontendPort == 0 { lite_server.go
95 > cfg.FrontendPort = freeport.MustGetFreePort()
96 > }
97 > if cfg.MetricsPort == 0 {
98 > cfg.MetricsPort = freeport.MustGetFreePort()
99 > }
100 > pprofPort := freeport.MustGetFreePort()
101 >
102 > serverConfig.Global.Membership = config.Membership{
103 > MaxJoinDuration: 30 * time.Second,
104 > BroadcastAddress: localBroadcastAddress,
105 > }
106 > serverConfig.Global.Metrics = &metrics.Config{
107 > Prometheus: &metrics.PrometheusConfig{
108 > ListenAddress: fmt.Sprintf("%s:%d", cfg.FrontendIP, cfg.MetricsPort),
109 > HandlerPath: "/metrics",
110 > },
111 > }
112 > serverConfig.Global.PProf = config.PProf{Port: pprofPort}
113 > serverConfig.Persistence = config.Persistence{
114 > DefaultStore: sqliteplugin.PluginName,
115 > VisibilityStore: sqliteplugin.PluginName,
116 > NumHistoryShards: 1,
117 > DataStores: map[string]config.DataStore{
118 > sqliteplugin.PluginName: {SQL: &sqliteConfig},
119 > },
120 > }
121 > serverConfig.ClusterMetadata = &cluster.Config{
122 > EnableGlobalNamespace: false,
123 > FailoverVersionIncrement: 10,
124 > MasterClusterName: "active",
125 > CurrentClusterName: "active",
126 > ClusterInformation: map[string]cluster.ClusterInformation{
127 > "active": {
128 > Enabled: true,
129 > InitialFailoverVersion: 1,
130 > RPCAddress: fmt.Sprintf("%s:%d", localBroadcastAddress, cfg.FrontendPort),
131 > },
132 > },
133 > }
134 > serverConfig.DCRedirectionPolicy = config.DCRedirectionPolicy{
135 > Policy: "noop",
136 > }
137 > serverConfig.Services = map[string]config.Service{
138 > "frontend": cfg.mustGetService(0),
139 > "history": cfg.mustGetService(1),
140 > "matching": cfg.mustGetService(2),
141 > "worker": cfg.mustGetService(3),
142 > }
143 > serverConfig.Archival = config.Archival{
144 > History: config.HistoryArchival{
145 > State: "disabled",
146 > EnableRead: false,
147 > Provider: nil,
148 > },
149 > Visibility: config.VisibilityArchival{
150 > State: "disabled",
151 > EnableRead: false,
152 > Provider: nil,
153 > },
154 > }
155 > // TODO(dnr): Figure out why server fails to start when PublicClient is not set with error:
156 > // panic: Client must be created with client.Dial() or client.NewLazyClient()
157 > // See also: https://github.com/temporalio/temporal/pull/4026#discussion_r1149808018
158 > serverConfig.PublicClient = config.PublicClient{
159 > HostPort: fmt.Sprintf("%s:%d", localBroadcastAddress, cfg.FrontendPort),
160 > }
161 > serverConfig.NamespaceDefaults = config.NamespaceDefaults{
162 > Archival: config.ArchivalNamespaceDefaults{
163 > History: config.HistoryArchivalNamespaceDefaults{
164 > State: "disabled",
165 > },
166 > Visibility: config.VisibilityArchivalNamespaceDefaults{
167 > State: "disabled",
168 > },
169 > },
170 > }
171 }
172
173 > func (cfg *LiteServerConfig) applyDefaults() { lite_server.go
174 > if cfg.BaseConfig == nil {
175 > cfg.BaseConfig = &config.Config{}
176 > }
177 > if cfg.Logger == nil {
178 cfg.Logger = log.NewZapLogger(log.BuildZapLogger(log.Config{
179 Stdout: true,
184 }
185
186 > func (cfg *LiteServerConfig) validate() error { lite_server.go
187 > for pragma := range cfg.SQLitePragmas {
188 if _, ok := supportedPragmas[strings.ToLower(pragma)]; !ok {
189 return fmt.Errorf("unsupported SQLite pragma %q. allowed pragmas: %v", pragma, getAllowedPragmas())
191 }
192
193 > if cfg.Ephemeral && cfg.DatabaseFilePath != "" { lite_server.go
194 return fmt.Errorf("config option DatabaseFilePath is not supported in ephemeral mode")
195 }
196 > if !cfg.Ephemeral && cfg.DatabaseFilePath == "" { lite_server.go
197 return fmt.Errorf("config option DatabaseFilePath is required when ephemeral mode disabled")
198 }
199
200 > return nil lite_server.go
201 }
202
214 // Always use BaseConfig instead of the WithConfig server option, as WithConfig overrides all
215 // LiteServer specific settings.
216 > func NewLiteServer(liteConfig *LiteServerConfig, opts ...temporal.ServerOption) (*LiteServer, error) { lite_server.go
217 > liteConfig.applyDefaults()
218 > if err := liteConfig.validate(); err != nil {
219 return nil, err
220 }
221
222 > liteConfig.apply(liteConfig.BaseConfig) lite_server.go
223 >
224 > sqlConfig := liteConfig.BaseConfig.Persistence.DataStores[sqliteplugin.PluginName].SQL
225 >
226 > if !liteConfig.Ephemeral {
227 // Apply migrations if file does not already exist
228 if _, err := os.Stat(liteConfig.DatabaseFilePath); os.IsNotExist(err) {
240
241 // Pre-create namespaces
242 > var namespaces []*sqlite.NamespaceConfig lite_server.go
243 > for _, ns := range liteConfig.Namespaces {
244 > nsConfig, err := sqlite.NewNamespaceConfig(
245 > liteConfig.BaseConfig.ClusterMetadata.CurrentClusterName,
246 > ns,
247 > false,
248 > liteConfig.SearchAttributes,
249 > )
250 > if err != nil {
251 return nil, fmt.Errorf("error creating namespace config: %w", err)
252 }
253 > namespaces = append(namespaces, nsConfig) lite_server.go
254 }
255 > if err := sqlite.CreateNamespaces(sqlConfig, namespaces...); err != nil { lite_server.go
256 return nil, fmt.Errorf("error creating namespaces: %w", err)
257 }
258
259 > authorizer, err := authorization.GetAuthorizerFromConfig(&liteConfig.BaseConfig.Global.Authorization) lite_server.go
260 > if err != nil {
261 return nil, fmt.Errorf("unable to instantiate authorizer: %w", err)
262 }
263
264 > claimMapper, err := authorization.GetClaimMapperFromConfig(&liteConfig.BaseConfig.Global.Authorization, liteConfig.Logger) lite_server.go
265 > if err != nil {
266 return nil, fmt.Errorf("unable to instantiate claim mapper: %w", err)
267 }
268
269 > serverOpts := []temporal.ServerOption{ lite_server.go
270 > temporal.WithConfig(liteConfig.BaseConfig),
271 > temporal.ForServices(temporal.DefaultServices),
272 > temporal.WithLogger(liteConfig.Logger),
273 > temporal.WithAuthorizer(authorizer),
274 > temporal.WithClaimMapper(func(cfg *config.Config) authorization.ClaimMapper {
275 > return claimMapper
276 > }),
277 }
278
279 > if len(liteConfig.DynamicConfig) > 0 { lite_server.go
280 > // To prevent having to code fall-through semantics right now, we currently
281 > // eagerly fail if dynamic config is being configured in two ways
282 > if liteConfig.BaseConfig.DynamicConfigClient != nil {
283 return nil, fmt.Errorf("unable to have file-based dynamic config and individual dynamic config values")
284 }
285 > serverOpts = append(serverOpts, temporal.WithDynamicConfigClient(liteConfig.DynamicConfig)) lite_server.go
286 }
287
288 // Apply options from arguments
289 > serverOpts = append(serverOpts, opts...) lite_server.go
290 >
291 > srv, err := temporal.NewServer(serverOpts...)
292 > if err != nil {
293 return nil, fmt.Errorf("unable to instantiate server: %w", err)
294 }
295
296 > s := &LiteServer{ lite_server.go
297 > internal: srv,
298 > frontendHostPort: liteConfig.BaseConfig.PublicClient.HostPort,
299 > }
300 >
301 > return s, nil
302 }
303
304 // Start temporal server.
305 > func (s *LiteServer) Start() error { lite_server.go
306 > // We wrap Server instead of simply embedding it in the LiteServer struct so
307 > // that it's possible to add additional lifecycle hooks here if necessary.
308 > return s.internal.Start()
309 > }
310
311 // Stop the server.
312 > func (s *LiteServer) Stop() error { lite_server.go
313 > // We wrap Server instead of simply embedding it in the LiteServer struct so
314 > // that it's possible to add additional lifecycle hooks here if necessary.
315 > return s.internal.Stop()
316 > }
317
318 // NewClient initializes a client ready to communicate with the Temporal
327 //
328 // Note that options.HostPort will always be overridden.
329 > func (s *LiteServer) NewClientWithOptions(ctx context.Context, options client.Options) (client.Client, error) { lite_server.go
330 > options.HostPort = s.frontendHostPort
331 > return client.Dial(options)
332 > }
333
334 // FrontendHostPort returns the host:port for this server.
351 }
352
353 > func (cfg *LiteServerConfig) mustGetService(frontendPortOffset int) config.Service { lite_server.go
354 > svc := config.Service{
355 > RPC: config.RPC{
356 > GRPCPort: cfg.FrontendPort + frontendPortOffset,
357 > MembershipPort: freeport.MustGetFreePort(),
358 > BindOnLocalHost: true,
359 > BindOnIP: "",
360 > },
361 > }
362 >
363 > // Assign any open port when configured to use dynamic ports
364 > if frontendPortOffset != 0 {
365 > svc.RPC.GRPCPort = freeport.MustGetFreePort()
366 > }
367
368 // Optionally bind frontend to IPv4 address
369 > if frontendPortOffset == 0 && cfg.FrontendIP != "" { lite_server.go
370 > svc.RPC.BindOnLocalHost = false
371 > svc.RPC.BindOnIP = cfg.FrontendIP
372 > }
373
374 > return svc lite_server.go
375 }
go.temporal.io/server/service/history/history_engine.go 164 covered LOC · 16 ranges

Open complete file

182 testHooks testhooks.TestHooks,
183 chasmEngine chasm.Engine,
184 > ) historyi.Engine { history_engine.go
185 > currentClusterName := shard.GetClusterMetadata().GetCurrentClusterName()
186 >
187 > logger := shard.GetLogger()
188 > executionManager := shard.GetExecutionManager()
189 >
190 > workflowDeleteManager := deletemanager.NewDeleteManager(
191 > shard,
192 > workflowCache,
193 > config,
194 > shard.GetTimeSource(),
195 > persistenceVisibilityMgr,
196 > )
197 > syncStateRetriever := replication.NewSyncStateRetriever(
198 > shard,
199 > workflowCache,
200 > workflowConsistencyChecker,
201 > eventBlobCache,
202 > shard.GetLogger(),
203 > )
204 >
205 > historyEngImpl := &historyEngineImpl{
206 > status: common.DaemonStatusInitialized,
207 > currentClusterName: currentClusterName,
208 > shardContext: shard,
209 > clusterMetadata: shard.GetClusterMetadata(),
210 > timeSource: shard.GetTimeSource(),
211 > executionManager: executionManager,
212 > tokenSerializer: tasktoken.NewSerializer(),
213 > logger: log.With(logger, tag.ComponentHistoryEngine),
214 > throttledLogger: log.With(shard.GetThrottledLogger(), tag.ComponentHistoryEngine),
215 > metricsHandler: shard.GetMetricsHandler(),
216 > eventNotifier: eventNotifier,
217 > config: config,
218 > sdkClientFactory: sdkClientFactory,
219 > matchingClient: matchingClient,
220 > rawMatchingClient: rawMatchingClient,
221 > persistenceVisibilityMgr: persistenceVisibilityMgr,
222 > workflowDeleteManager: workflowDeleteManager,
223 > serializer: serializer,
224 > workflowConsistencyChecker: workflowConsistencyChecker,
225 > versionChecker: headers.NewDefaultVersionChecker(),
226 > tracer: tracerProvider.Tracer(consts.LibraryName),
227 > taskCategoryRegistry: taskCategoryRegistry,
228 > commandHandlerRegistry: commandHandlerRegistry,
229 > chasmWorkflowRegistry: chasmWorkflowRegistry,
230 > workflowCache: workflowCache,
231 > replicationProgressCache: replicationProgressCache,
232 > syncStateRetriever: syncStateRetriever,
233 > outboundQueueCBPool: outboundQueueCBPool,
234 > testHooks: testHooks,
235 > chasmEngine: chasmEngine,
236 > versionCache: versionCache,
237 > workerDeploymentClient: workerDeploymentClient,
238 > routingInfoCache: routingInfoCache,
239 > }
240 >
241 > historyEngImpl.queueProcessors = make(map[tasks.Category]queues.Queue)
242 > for _, factory := range queueProcessorFactories {
243 > processor := factory.CreateQueue(shard)
244 > historyEngImpl.queueProcessors[processor.Category()] = processor
245 > }
246
247 > historyEngImpl.eventsReapplier = ndc.NewEventsReapplier(shard.StateMachineRegistry(), shard.ChasmWorkflowRegistry(), shard.GetMetricsHandler(), logger) history_engine.go
248 >
249 > if shard.GetClusterMetadata().IsGlobalNamespaceEnabled() {
250 historyEngImpl.replicationAckMgr = replication.NewAckManager(
251 shard,
289 )
290 }
291 > historyEngImpl.workflowRebuilder = NewWorkflowRebuilder( history_engine.go
292 > shard,
293 > workflowCache,
294 > logger,
295 > )
296 > historyEngImpl.workflowResetter = ndc.NewWorkflowResetter(
297 > shard,
298 > workflowCache,
299 > logger,
300 > )
301 >
302 > historyEngImpl.searchAttributesValidator = searchattribute.NewValidator(
303 > shard.GetSearchAttributesProvider(),
304 > shard.GetSearchAttributesMapperProvider(),
305 > config.SearchAttributesNumberOfKeysLimit,
306 > config.SearchAttributesSizeOfValueLimit,
307 > config.SearchAttributesTotalSizeLimit,
308 > persistenceVisibilityMgr,
309 > visibility.AllowListForValidation(
310 > persistenceVisibilityMgr.GetStoreNames(),
311 > config.VisibilityAllowList,
312 > ),
313 > config.SuppressErrorSetSystemSearchAttribute,
314 > shard.GetMetricsHandler(),
315 > logger,
316 > )
317 >
318 > historyEngImpl.replicationDLQHandler = replication.NewLazyDLQHandler(
319 > shard,
320 > workflowDeleteManager,
321 > workflowCache,
322 > clientBean,
323 > replicationTaskExecutorProvider,
324 > )
325 > historyEngImpl.replicationProcessorMgr = replication.NewTaskProcessorManager(
326 > config,
327 > shard,
328 > historyEngImpl,
329 > workflowCache,
330 > workflowDeleteManager,
331 > clientBean,
332 > serializer,
333 > replicationTaskFetcherFactory,
334 > replicationTaskExecutorProvider,
335 > testHooks,
336 > dlqWriter,
337 > )
338 >
339 > return historyEngImpl
340 }
341
343 // Make sure all the components are loaded lazily so start can return immediately. This is important because
344 // ShardController calls start sequentially for all the shards for a given host during startup.
345 > func (e *historyEngineImpl) Start() { history_engine.go
346 > if !atomic.CompareAndSwapInt32(
347 > &e.status,
348 > common.DaemonStatusInitialized,
349 > common.DaemonStatusStarted,
350 > ) {
351 return
352 }
353
354 > e.logger.Info("", tag.LifeCycleStarting) history_engine.go
355 > defer e.logger.Info("", tag.LifeCycleStarted)
356 >
357 > e.registerNamespaceStateChangeCallback()
358 >
359 > for _, queueProcessor := range e.queueProcessors {
360 > queueProcessor.Start()
361 > }
362 > e.replicationProcessorMgr.Start()
363 }
364
365 // Stop the service.
366 > func (e *historyEngineImpl) Stop() { history_engine.go
367 > if !atomic.CompareAndSwapInt32(
368 > &e.status,
369 > common.DaemonStatusStarted,
370 > common.DaemonStatusStopped,
371 > ) {
372 return
373 }
374
375 > e.logger.Info("", tag.LifeCycleStopping) history_engine.go
376 > defer e.logger.Info("", tag.LifeCycleStopped)
377 >
378 > for _, queueProcessor := range e.queueProcessors {
379 > queueProcessor.Stop()
380 > }
381 > e.replicationProcessorMgr.Stop()
382 > // unset the failover callback
383 > e.shardContext.GetNamespaceRegistry().UnregisterStateChangeCallback(e)
384 }
385
386 > func (e *historyEngineImpl) registerNamespaceStateChangeCallback() { history_engine.go
387 >
388 > e.shardContext.GetNamespaceRegistry().RegisterStateChangeCallback(e, func(ns *namespace.Namespace, deletedFromDb bool) {
389 > if e.shardContext.GetClusterMetadata().IsGlobalNamespaceEnabled() {
390 e.shardContext.UpdateHandoverNamespace(ns, deletedFromDb)
391 }
392
393 > if deletedFromDb { history_engine.go
394 return
395 }
396
397 > if ns.IsGlobalNamespace() && history_engine.go
398 > ns.ReplicationPolicy() == namespace.ReplicationPolicyMultiCluster &&
399 > //nolint:forbidigo // namespace state-change callback; FailoverNamespace operates per-namespace, no workflow context
400 > ns.ActiveInCluster(e.currentClusterName) {
401
402 for _, queueProcessor := range e.queueProcessors {
887 func (e *historyEngineImpl) NotifyNewTasks(
888 newTasks map[tasks.Category][]tasks.Task,
889 > ) { history_engine.go
890 > for category, tasksByCategory := range newTasks {
891 > // TODO: make replicatorProcessor part of queueProcessors list history_engine.go
892 > // and get rid of the special case here.
893 > if category == tasks.CategoryReplication {
894 > if e.replicationAckMgr != nil { history_engine.go
895 e.replicationAckMgr.NotifyNewTasks(tasksByCategory)
896 }
897 > continue history_engine.go
898 }
899
900 > if len(tasksByCategory) > 0 { history_engine.go
901 > proc, ok := e.queueProcessors[category]
902 > if !ok {
903 // On shard reload it sends fake tasks to wake up the queue processors. Only log if there are "real"
904 // tasks that can't be processed.
908 continue
909 }
910 > proc.NotifyNewTasks(tasksByCategory) history_engine.go
911 }
912 }
go.temporal.io/server/service/history/timer_queue_factory.go 162 covered LOC · 3 ranges

Open complete file

39 func NewTimerQueueFactory(
40 params timerQueueFactoryParams,
41 > ) QueueFactory { timer_queue_factory.go
42 > return &timerQueueFactory{
43 > timerQueueFactoryParams: params,
44 > QueueFactoryBase: QueueFactoryBase{
45 > HostScheduler: queues.NewScheduler(
46 > params.ClusterMetadata.GetCurrentClusterName(),
47 > queues.SchedulerOptions{
48 > WorkerCount: params.Config.TimerProcessorSchedulerWorkerCount,
49 > ActiveNamespaceWeights: params.Config.TimerProcessorSchedulerActiveRoundRobinWeights,
50 > StandbyNamespaceWeights: params.Config.TimerProcessorSchedulerStandbyRoundRobinWeights,
51 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
52 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
53 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
54 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
55 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
56 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
57 > },
58 > },
59 > params.NamespaceRegistry,
60 > params.Logger,
61 > params.MetricsHandler,
62 > params.TimeSource,
63 > ),
64 > HostPriorityAssigner: queues.NewPriorityAssigner(
65 > params.NamespaceRegistry,
66 > params.ClusterMetadata.GetCurrentClusterName(),
67 > ),
68 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
69 > NewHostRateLimiterRateFn(
70 > params.Config.TimerProcessorMaxPollHostRPS,
71 > params.Config.PersistenceMaxQPS,
72 > timerQueuePersistenceMaxRPSRatio,
73 > ),
74 > int64(params.Config.TimerQueueMaxReaderCount()),
75 > ),
76 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueTimer),
77 > },
78 > }
79 > }
80
81 func (f *timerQueueFactory) CreateQueue(
82 shardContext historyi.ShardContext,
83 > ) queues.Queue { timer_queue_factory.go
84 > logger := log.With(shardContext.GetLogger(), tag.ComponentTimerQueue)
85 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationTimerQueueProcessorScope))
86 >
87 > currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
88 > workflowDeleteManager := deletemanager.NewDeleteManager(
89 > shardContext,
90 > f.WorkflowCache,
91 > f.Config,
92 > shardContext.GetTimeSource(),
93 > f.VisibilityManager,
94 > )
95 >
96 > shardScheduler := queues.NewRateLimitedScheduler(
97 > f.HostScheduler,
98 > queues.RateLimitedSchedulerOptions{
99 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
100 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
101 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
102 > },
103 > currentClusterName,
104 > f.NamespaceRegistry,
105 > f.SchedulerRateLimiter,
106 > f.TimeSource,
107 > f.ChasmRegistry,
108 > logger,
109 > metricsHandler,
110 > )
111 >
112 > rescheduler := queues.NewRescheduler(
113 > shardScheduler,
114 > shardContext.GetTimeSource(),
115 > logger,
116 > metricsHandler,
117 > )
118 >
119 > activeExecutor := newTimerQueueActiveTaskExecutor(
120 > shardContext,
121 > f.WorkflowCache,
122 > workflowDeleteManager,
123 > logger,
124 > f.MetricsHandler,
125 > f.Config,
126 > f.MatchingRawClient,
127 > f.ChasmEngine,
128 > )
129 >
130 > standbyExecutor := newTimerQueueStandbyTaskExecutor(
131 > shardContext,
132 > f.WorkflowCache,
133 > workflowDeleteManager,
134 > f.MatchingRawClient,
135 > f.ChasmEngine,
136 > logger,
137 > f.MetricsHandler,
138 > // note: the cluster name is for calculating time for standby tasks,
139 > // here we are basically using current cluster time
140 > // this field will be deprecated soon, currently exists so that
141 > // we have the option of revert to old behavior
142 > currentClusterName,
143 > f.Config,
144 > f.ClientBean,
145 > )
146 >
147 > executor := queues.NewActiveStandbyExecutor(
148 > currentClusterName,
149 > f.NamespaceRegistry,
150 > activeExecutor,
151 > standbyExecutor,
152 > logger,
153 > )
154 > if f.ExecutorWrapper != nil {
155 executor = f.ExecutorWrapper.Wrap(executor)
156 }
157
158 > factory := queues.NewExecutableFactory( timer_queue_factory.go
159 > executor,
160 > shardScheduler,
161 > rescheduler,
162 > f.HostPriorityAssigner,
163 > shardContext.GetTimeSource(),
164 > shardContext.GetNamespaceRegistry(),
165 > shardContext.GetClusterMetadata(),
166 > f.ChasmRegistry,
167 > queues.GetTaskTypeTagValue,
168 > logger,
169 > metricsHandler,
170 > f.Tracer,
171 > f.DLQWriter,
172 > f.Config.TaskDLQEnabled,
173 > f.Config.TaskDLQUnexpectedErrorAttempts,
174 > f.Config.TaskDLQInternalErrors,
175 > f.Config.TaskDLQErrorPattern,
176 > )
177 > return queues.NewScheduledQueue(
178 > shardContext,
179 > tasks.CategoryTimer,
180 > shardScheduler,
181 > rescheduler,
182 > factory,
183 > &queues.Options{
184 > ReaderOptions: queues.ReaderOptions{
185 > BatchSize: f.Config.TimerTaskBatchSize,
186 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
187 > PollBackoffInterval: f.Config.TimerProcessorPollBackoffInterval,
188 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
189 > },
190 > MonitorOptions: queues.MonitorOptions{
191 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
192 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
193 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
194 > },
195 > MaxPollRPS: f.Config.TimerProcessorMaxPollRPS,
196 > MaxPollInterval: f.Config.TimerProcessorMaxPollInterval,
197 > MaxPollIntervalJitterCoefficient: f.Config.TimerProcessorMaxPollIntervalJitterCoefficient,
198 > CheckpointInterval: f.Config.TimerProcessorUpdateAckInterval,
199 > CheckpointIntervalJitterCoefficient: f.Config.TimerProcessorUpdateAckIntervalJitterCoefficient,
200 > MaxReaderCount: f.Config.TimerQueueMaxReaderCount,
201 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
202 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
203 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
204 > },
205 > f.HostReaderRateLimiter,
206 > logger,
207 > metricsHandler,
208 > )
209 }
go.temporal.io/server/common/persistence/persistence_rate_limited_clients.go 159 covered LOC · 47 ranges

Open complete file

112 shardRateLimiter quotas.RequestRateLimiter,
113 logger log.Logger,
114 > ) ShardManager { persistence_rate_limited_clients.go
115 > return &shardRateLimitedPersistenceClient{
116 > persistence: persistence,
117 > systemRateLimiter: rateLimiter,
118 > namespaceRateLimiter: namespaceRateLimiter,
119 > shardRateLimiter: shardRateLimiter,
120 > logger: logger,
121 > }
122 > }
123
124 // NewExecutionPersistenceRateLimitedClient creates a client to manage executions
129 shardRateLimiter quotas.RequestRateLimiter,
130 logger log.Logger,
131 > ) ExecutionManager { persistence_rate_limited_clients.go
132 > return &executionRateLimitedPersistenceClient{
133 > persistence: persistence,
134 > systemRateLimiter: systemRateLimiter,
135 > namespaceRateLimiter: namespaceRateLimiter,
136 > shardRateLimiter: shardRateLimiter,
137 > logger: logger,
138 > }
139 > }
140
141 // NewTaskPersistenceRateLimitedClient creates a client to manage tasks
146 shardRateLimiter quotas.RequestRateLimiter,
147 logger log.Logger,
148 > ) TaskManager { persistence_rate_limited_clients.go
149 > return &taskRateLimitedPersistenceClient{
150 > persistence: persistence,
151 > systemRateLimiter: systemRateLimiter,
152 > namespaceRateLimiter: namespaceRateLimiter,
153 > shardRateLimiter: shardRateLimiter,
154 > logger: logger,
155 > }
156 > }
157
158 // NewMetadataPersistenceRateLimitedClient creates a MetadataManager client to manage metadata
163 shardRateLimiter quotas.RequestRateLimiter,
164 logger log.Logger,
165 > ) MetadataManager { persistence_rate_limited_clients.go
166 > return &metadataRateLimitedPersistenceClient{
167 > persistence: persistence,
168 > systemRateLimiter: systemRateLimiter,
169 > namespaceRateLimiter: namespaceRateLimiter,
170 > shardRateLimiter: shardRateLimiter,
171 > logger: logger,
172 > }
173 > }
174
175 // NewClusterMetadataPersistenceRateLimitedClient creates a ClusterMetadataManager client to manage cluster metadata
180 shardRateLimiter quotas.RequestRateLimiter,
181 logger log.Logger,
182 > ) ClusterMetadataManager { persistence_rate_limited_clients.go
183 > return &clusterMetadataRateLimitedPersistenceClient{
184 > persistence: persistence,
185 > systemRateLimiter: systemRateLimiter,
186 > namespaceRateLimiter: namespaceRateLimiter,
187 > shardRateLimiter: shardRateLimiter,
188 > logger: logger,
189 > }
190 > }
191
192 // NewQueuePersistenceRateLimitedClient creates a client to manage queue
197 shardRateLimiter quotas.RequestRateLimiter,
198 logger log.Logger,
200 > return &queueRateLimitedPersistenceClient{
201 > persistence: persistence,
202 > systemRateLimiter: systemRateLimiter,
203 > namespaceRateLimiter: namespaceRateLimiter,
204 > shardRateLimiter: shardRateLimiter,
205 > logger: logger,
206 > }
207 > }
208
209 // NewNexusEndpointPersistenceRateLimitedClient creates a NexusEndpointManager to manage nexus endpoints
214 shardRateLimiter quotas.RequestRateLimiter,
215 logger log.Logger,
216 > ) NexusEndpointManager { persistence_rate_limited_clients.go
217 > return &nexusEndpointRateLimitedPersistenceClient{
218 > persistence: persistence,
219 > systemRateLimiter: systemRateLimiter,
220 > namespaceRateLimiter: namespaceRateLimiter,
221 > shardRateLimiter: shardRateLimiter,
222 > logger: logger,
223 > }
224 > }
225
226 func (p *shardRateLimitedPersistenceClient) GetName() string {
231 ctx context.Context,
232 request *GetOrCreateShardRequest,
233 > ) (*GetOrCreateShardResponse, error) { persistence_rate_limited_clients.go
234 > if err := allow(ctx, "GetOrCreateShard", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
235 return nil, err
236 }
237
238 > response, err := p.persistence.GetOrCreateShard(ctx, request) persistence_rate_limited_clients.go
239 > return response, err
240 }
241
243 ctx context.Context,
244 request *UpdateShardRequest,
246 > if err := allow(ctx, "UpdateShard", request.ShardInfo.ShardId, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
247 return err
248 }
249
250 > return p.persistence.UpdateShard(ctx, request) persistence_rate_limited_clients.go
251 }
252
254 ctx context.Context,
255 request *AssertShardOwnershipRequest,
257 > if err := allow(ctx, "AssertShardOwnership", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
258 return err
259 }
260
261 > return p.persistence.AssertShardOwnership(ctx, request) persistence_rate_limited_clients.go
262 }
263
264 > func (p *shardRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
265 > p.persistence.Close()
266 > }
267
268 > func (p *executionRateLimitedPersistenceClient) GetName() string { persistence_rate_limited_clients.go
269 > return p.persistence.GetName()
270 > }
271
272 func (p *executionRateLimitedPersistenceClient) GetHistoryBranchUtil() HistoryBranchUtil {
394 ctx context.Context,
395 request *GetHistoryTasksRequest,
396 > ) (*GetHistoryTasksResponse, error) { persistence_rate_limited_clients.go
397 > if err := allow(
398 > ctx,
399 > ConstructHistoryTaskAPI("GetHistoryTasks", request.TaskCategory),
400 > request.ShardID,
401 > p.systemRateLimiter,
402 > p.namespaceRateLimiter,
403 > p.shardRateLimiter,
404 > ); err != nil {
405 return nil, err
406 }
407
408 > response, err := p.persistence.GetHistoryTasks(ctx, request) persistence_rate_limited_clients.go
409 > return response, err
410 }
411
501 }
502
503 > func (p *executionRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
504 > p.persistence.Close()
505 > }
506
507 func (p *taskRateLimitedPersistenceClient) GetName() string {
637 }
638
639 > func (p *taskRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
640 > p.persistence.Close()
641 > }
642
643 func (p *metadataRateLimitedPersistenceClient) GetName() string {
660 ctx context.Context,
661 request *GetNamespaceRequest,
662 > ) (*GetNamespaceResponse, error) { persistence_rate_limited_clients.go
663 > if err := allow(ctx, "GetNamespace", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
664 return nil, err
665 }
666
667 > response, err := p.persistence.GetNamespace(ctx, request) persistence_rate_limited_clients.go
668 > return response, err
669 }
670
716 ctx context.Context,
717 request *ListNamespacesRequest,
718 > ) (*ListNamespacesResponse, error) { persistence_rate_limited_clients.go
719 > if err := allow(ctx, "ListNamespaces", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
720 return nil, err
721 }
722
723 > response, err := p.persistence.ListNamespaces(ctx, request) persistence_rate_limited_clients.go
724 > return response, err
725 }
726
748 func (p *metadataRateLimitedPersistenceClient) WatchNamespaces(
749 ctx context.Context,
750 > ) (<-chan *NamespaceWatchEvent, error) { persistence_rate_limited_clients.go
751 > if err := allow(ctx, "WatchNamespaces", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
752 return nil, err
753 }
754 > return p.persistence.WatchNamespaces(ctx) persistence_rate_limited_clients.go
755 }
756
757 > func (p *metadataRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
758 > p.persistence.Close()
759 > }
760
761 // AppendHistoryNodes add a node to history node table
998 }
999
1000 > func (p *queueRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
1001 > p.persistence.Close()
1002 > }
1003
1004 func (p *queueRateLimitedPersistenceClient) Init(
1005 ctx context.Context,
1006 blob *commonpb.DataBlob,
1008 > return p.persistence.Init(ctx, blob)
1009 > }
1010
1011 > func (c *clusterMetadataRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
1012 > c.persistence.Close()
1013 > }
1014
1015 func (c *clusterMetadataRateLimitedPersistenceClient) GetName() string {
1020 ctx context.Context,
1021 request *GetClusterMembersRequest,
1022 > ) (*GetClusterMembersResponse, error) { persistence_rate_limited_clients.go
1023 > if err := allow(ctx, "GetClusterMembers", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1024 return nil, err
1025 }
1026 > return c.persistence.GetClusterMembers(ctx, request) persistence_rate_limited_clients.go
1027 }
1028
1030 ctx context.Context,
1031 request *UpsertClusterMembershipRequest,
1033 > if err := allow(ctx, "UpsertClusterMembership", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1034 return err
1035 }
1036 > return c.persistence.UpsertClusterMembership(ctx, request) persistence_rate_limited_clients.go
1037 }
1038
1040 ctx context.Context,
1041 request *PruneClusterMembershipRequest,
1043 > if err := allow(ctx, "PruneClusterMembership", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1044 return err
1045 }
1046 > return c.persistence.PruneClusterMembership(ctx, request) persistence_rate_limited_clients.go
1047 }
1048
1050 ctx context.Context,
1051 request *ListClusterMetadataRequest,
1052 > ) (*ListClusterMetadataResponse, error) { persistence_rate_limited_clients.go
1053 > if err := allow(ctx, "ListClusterMetadata", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1054 return nil, err
1055 }
1056 > return c.persistence.ListClusterMetadata(ctx, request) persistence_rate_limited_clients.go
1057 }
1058
1059 func (c *clusterMetadataRateLimitedPersistenceClient) GetCurrentClusterMetadata(
1060 ctx context.Context,
1061 > ) (*GetClusterMetadataResponse, error) { persistence_rate_limited_clients.go
1062 > if err := allow(ctx, "GetCurrentClusterMetadata", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1063 return nil, err
1064 }
1065 > return c.persistence.GetCurrentClusterMetadata(ctx) persistence_rate_limited_clients.go
1066 }
1067
1100 }
1101
1102 > func (p *nexusEndpointRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
1103 > p.persistence.Close()
1104 > }
1105
1106 func (p *nexusEndpointRateLimitedPersistenceClient) GetNexusEndpoint(
1117 ctx context.Context,
1118 request *ListNexusEndpointsRequest,
1119 > ) (*ListNexusEndpointsResponse, error) { persistence_rate_limited_clients.go
1120 > if err := allow(ctx, "ListNexusEndpoints", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
1121 return nil, err
1122 }
1123 > return p.persistence.ListNexusEndpoints(ctx, request) persistence_rate_limited_clients.go
1124 }
1125
1151 namespaceRateLimiter quotas.RequestRateLimiter,
1152 shardRateLimiter quotas.RequestRateLimiter,
1154 > callerInfo := headers.GetCallerInfo(ctx)
1155 > // namespace-level rate limits has to be applied before system-level rate limits.
1156 > now := time.Now().UTC()
1157 > quotaRequest := quotas.NewRequest(
1158 > api,
1159 > RateLimitDefaultToken,
1160 > callerInfo.CallerName,
1161 > callerInfo.CallerType,
1162 > shardID,
1163 > callerInfo.CallOrigin,
1164 > )
1165 > if ok := shardRateLimiter.Allow(now, quotaRequest); !ok {
1166 return ErrPersistenceNamespaceShardLimitExceeded
1167 }
1168 > if ok := namespaceRateLimiter.Allow(now, quotaRequest); !ok { persistence_rate_limited_clients.go
1169 return ErrPersistenceNamespaceLimitExceeded
1170 }
1171 > if ok := systemRateLimiter.Allow(now, quotaRequest); !ok { persistence_rate_limited_clients.go
1172 return ErrPersistenceSystemLimitExceeded
1173 }
1175 }
1176
go.temporal.io/server/service/history/transfer_queue_factory.go 157 covered LOC · 3 ranges

Open complete file

46 func NewTransferQueueFactory(
47 params transferQueueFactoryParams,
48 > ) QueueFactory { transfer_queue_factory.go
49 > return &transferQueueFactory{
50 > transferQueueFactoryParams: params,
51 > QueueFactoryBase: QueueFactoryBase{
52 > HostScheduler: queues.NewScheduler(
53 > params.ClusterMetadata.GetCurrentClusterName(),
54 > queues.SchedulerOptions{
55 > WorkerCount: params.Config.TransferProcessorSchedulerWorkerCount,
56 > ActiveNamespaceWeights: params.Config.TransferProcessorSchedulerActiveRoundRobinWeights,
57 > StandbyNamespaceWeights: params.Config.TransferProcessorSchedulerStandbyRoundRobinWeights,
58 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
59 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
60 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
61 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
62 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
63 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
64 > },
65 > },
66 > params.NamespaceRegistry,
67 > params.Logger,
68 > params.MetricsHandler,
69 > params.TimeSource,
70 > ),
71 > HostPriorityAssigner: queues.NewPriorityAssigner(
72 > params.NamespaceRegistry,
73 > params.ClusterMetadata.GetCurrentClusterName(),
74 > ),
75 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
76 > NewHostRateLimiterRateFn(
77 > params.Config.TransferProcessorMaxPollHostRPS,
78 > params.Config.PersistenceMaxQPS,
79 > transferQueuePersistenceMaxRPSRatio,
80 > ),
81 > int64(params.Config.TransferQueueMaxReaderCount()),
82 > ),
83 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueTransfer),
84 > },
85 > }
86 > }
87
88 func (f *transferQueueFactory) CreateQueue(
89 shardContext historyi.ShardContext,
90 > ) queues.Queue { transfer_queue_factory.go
91 > logger := log.With(shardContext.GetLogger(), tag.ComponentTransferQueue)
92 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationTransferQueueProcessorScope))
93 >
94 > currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
95 >
96 > shardScheduler := queues.NewRateLimitedScheduler(
97 > f.HostScheduler,
98 > queues.RateLimitedSchedulerOptions{
99 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
100 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
101 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
102 > },
103 > currentClusterName,
104 > f.NamespaceRegistry,
105 > f.SchedulerRateLimiter,
106 > f.TimeSource,
107 > f.ChasmRegistry,
108 > logger,
109 > metricsHandler,
110 > )
111 >
112 > rescheduler := queues.NewRescheduler(
113 > shardScheduler,
114 > shardContext.GetTimeSource(),
115 > logger,
116 > metricsHandler,
117 > )
118 >
119 > activeExecutor := newTransferQueueActiveTaskExecutor(
120 > shardContext,
121 > f.WorkflowCache,
122 > f.SdkClientFactory,
123 > logger,
124 > f.MetricsHandler,
125 > f.Config,
126 > f.HistoryRawClient,
127 > f.MatchingRawClient,
128 > f.VisibilityManager,
129 > f.ChasmEngine,
130 > f.VersionMembershipCache,
131 > f.TestHooks,
132 > )
133 >
134 > standbyExecutor := newTransferQueueStandbyTaskExecutor(
135 > shardContext,
136 > f.WorkflowCache,
137 > logger,
138 > f.MetricsHandler,
139 > currentClusterName,
140 > f.HistoryRawClient,
141 > f.MatchingRawClient,
142 > f.VisibilityManager,
143 > f.ChasmEngine,
144 > f.ClientBean,
145 > )
146 >
147 > executor := queues.NewActiveStandbyExecutor(
148 > currentClusterName,
149 > f.NamespaceRegistry,
150 > activeExecutor,
151 > standbyExecutor,
152 > logger,
153 > )
154 > if f.ExecutorWrapper != nil {
155 executor = f.ExecutorWrapper.Wrap(executor)
156 }
157
158 > factory := queues.NewExecutableFactory( transfer_queue_factory.go
159 > executor,
160 > shardScheduler,
161 > rescheduler,
162 > f.HostPriorityAssigner,
163 > shardContext.GetTimeSource(),
164 > shardContext.GetNamespaceRegistry(),
165 > shardContext.GetClusterMetadata(),
166 > f.ChasmRegistry,
167 > queues.GetTaskTypeTagValue,
168 > logger,
169 > metricsHandler,
170 > f.Tracer,
171 > f.DLQWriter,
172 > f.Config.TaskDLQEnabled,
173 > f.Config.TaskDLQUnexpectedErrorAttempts,
174 > f.Config.TaskDLQInternalErrors,
175 > f.Config.TaskDLQErrorPattern,
176 > )
177 > return queues.NewImmediateQueue(
178 > shardContext,
179 > tasks.CategoryTransfer,
180 > shardScheduler,
181 > rescheduler,
182 > &queues.Options{
183 > ReaderOptions: queues.ReaderOptions{
184 > BatchSize: f.Config.TransferTaskBatchSize,
185 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
186 > PollBackoffInterval: f.Config.TransferProcessorPollBackoffInterval,
187 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
188 > },
189 > MonitorOptions: queues.MonitorOptions{
190 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
191 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
192 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
193 > },
194 > MaxPollRPS: f.Config.TransferProcessorMaxPollRPS,
195 > MaxPollInterval: f.Config.TransferProcessorMaxPollInterval,
196 > MaxPollIntervalJitterCoefficient: f.Config.TransferProcessorMaxPollIntervalJitterCoefficient,
197 > CheckpointInterval: f.Config.TransferProcessorUpdateAckInterval,
198 > CheckpointIntervalJitterCoefficient: f.Config.TransferProcessorUpdateAckIntervalJitterCoefficient,
199 > MaxReaderCount: f.Config.TransferQueueMaxReaderCount,
200 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
201 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
202 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
203 > },
204 > f.HostReaderRateLimiter,
205 > queues.GrouperNamespaceID{},
206 > logger,
207 > metricsHandler,
208 > factory,
209 > nil, // taskPostProcessor
210 > )
211 }
go.temporal.io/server/service/history/outbound_queue_factory.go 149 covered LOC · 10 ranges

Open complete file

84 }
85
86 > func NewOutboundQueueFactory(params outboundQueueFactoryParams) QueueFactory { outbound_queue_factory.go
87 > metricsHandler := getOutbountQueueProcessorMetricsHandler(params.MetricsHandler)
88 >
89 > rateLimiterPool := collection.NewOnceMap(
90 > func(key tasks.TaskGroupNamespaceIDAndDestination) quotas.RateLimiter {
91 return quotas.NewDefaultOutgoingRateLimiter(func() float64 {
92 // This is intentionally not failing the function in case of error. The task
106 )
107
108 > grouper := queues.GrouperStateMachineNamespaceIDAndDestination{} outbound_queue_factory.go
109 > f := &outboundQueueFactory{
110 > outboundQueueFactoryParams: params,
111 > hostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
112 > NewHostRateLimiterRateFn(
113 > params.Config.OutboundProcessorMaxPollHostRPS,
114 > params.Config.PersistenceMaxQPS,
115 > outboundQueuePersistenceMaxRPSRatio,
116 > ),
117 > int64(params.Config.OutboundQueueMaxReaderCount()),
118 > ),
119 > hostScheduler: &queues.CommonSchedulerWrapper{
120 > Scheduler: ctasks.NewGroupByScheduler(
121 > ctasks.GroupBySchedulerOptions[
122 > tasks.TaskGroupNamespaceIDAndDestination,
123 > queues.Executable,
124 > ]{
125 > Logger: params.Logger,
126 > KeyFn: func(e queues.Executable) tasks.TaskGroupNamespaceIDAndDestination {
127 return grouper.KeyTyped(e.GetTask())
128 },
183 },
184 }
185 > return f outbound_queue_factory.go
186 }
187
188 // Start implements QueueFactory.
189 > func (f *outboundQueueFactory) Start() { outbound_queue_factory.go
190 > f.hostScheduler.Start()
191 > }
192
193 // Stop implements QueueFactory.
194 > func (f *outboundQueueFactory) Stop() { outbound_queue_factory.go
195 > f.hostScheduler.Stop()
196 > }
197
198 func (f *outboundQueueFactory) CreateQueue(
199 shardContext historyi.ShardContext,
200 > ) queues.Queue { outbound_queue_factory.go
201 > logger := log.With(shardContext.GetLogger(), tag.ComponentOutboundQueue)
202 > metricsHandler := getOutbountQueueProcessorMetricsHandler(f.MetricsHandler)
203 >
204 > currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
205 >
206 > scheduler := queues.NewRateLimitedScheduler(
207 > f.hostScheduler,
208 > queues.RateLimitedSchedulerOptions{
209 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
210 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
211 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
212 > },
213 > currentClusterName,
214 > f.NamespaceRegistry,
215 > f.SchedulerRateLimiter,
216 > f.TimeSource,
217 > f.ChasmRegistry,
218 > logger,
219 > metricsHandler,
220 > )
221 >
222 > rescheduler := queues.NewRescheduler(
223 > scheduler,
224 > shardContext.GetTimeSource(),
225 > logger,
226 > metricsHandler,
227 > )
228 >
229 > activeExecutor := newOutboundQueueActiveTaskExecutor(
230 > shardContext,
231 > f.WorkflowCache,
232 > logger,
233 > metricsHandler,
234 > f.ChasmEngine,
235 > f.MatchingClient,
236 > )
237 >
238 > standbyExecutor := newOutboundQueueStandbyTaskExecutor(
239 > shardContext,
240 > f.WorkflowCache,
241 > currentClusterName,
242 > logger,
243 > metricsHandler,
244 > f.ChasmEngine,
245 > f.ClientBean,
246 > )
247 >
248 > executor := queues.NewActiveStandbyExecutor(
249 > currentClusterName,
250 > f.NamespaceRegistry,
251 > activeExecutor,
252 > standbyExecutor,
253 > logger,
254 > )
255 >
256 > if f.ExecutorWrapper != nil {
257 executor = f.ExecutorWrapper.Wrap(executor)
258 }
259
260 > factory := queues.NewExecutableFactory( outbound_queue_factory.go
261 > executor,
262 > scheduler,
263 > rescheduler,
264 > queues.NewNoopPriorityAssigner(),
265 > shardContext.GetTimeSource(),
266 > shardContext.GetNamespaceRegistry(),
267 > shardContext.GetClusterMetadata(),
268 > f.ChasmRegistry,
269 > queues.GetTaskTypeTagValue,
270 > logger,
271 > metricsHandler,
272 > f.TracerProvider.Tracer(telemetry.ComponentQueueOutbound),
273 > f.DLQWriter,
274 > f.Config.TaskDLQEnabled,
275 > f.Config.TaskDLQUnexpectedErrorAttempts,
276 > f.Config.TaskDLQInternalErrors,
277 > f.Config.TaskDLQErrorPattern,
278 > )
279 > return queues.NewImmediateQueue(
280 > shardContext,
281 > tasks.CategoryOutbound,
282 > scheduler,
283 > rescheduler,
284 > &queues.Options{
285 > ReaderOptions: queues.ReaderOptions{
286 > BatchSize: f.Config.OutboundTaskBatchSize,
287 > MaxPendingTasksCount: f.Config.OutboundQueuePendingTaskMaxCount,
288 > PollBackoffInterval: f.Config.OutboundProcessorPollBackoffInterval,
289 > MaxPredicateSize: f.Config.OutboundQueueMaxPredicateSize,
290 > },
291 > MonitorOptions: queues.MonitorOptions{
292 > PendingTasksCriticalCount: f.Config.OutboundQueuePendingTaskCriticalCount,
293 > // Shared configuration with other queues.
294 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
295 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
296 > },
297 > MaxPollRPS: f.Config.OutboundProcessorMaxPollRPS,
298 > MaxPollInterval: f.Config.OutboundProcessorMaxPollInterval,
299 > MaxPollIntervalJitterCoefficient: f.Config.OutboundProcessorMaxPollIntervalJitterCoefficient,
300 > CheckpointInterval: f.Config.OutboundProcessorUpdateAckInterval,
301 > CheckpointIntervalJitterCoefficient: f.Config.OutboundProcessorUpdateAckIntervalJitterCoefficient,
302 > MaxReaderCount: f.Config.OutboundQueueMaxReaderCount,
303 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
304 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
305 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
306 > },
307 > f.hostReaderRateLimiter,
308 > queues.GrouperStateMachineNamespaceIDAndDestination{},
309 > logger,
310 > metricsHandler,
311 > factory,
312 > outboundTaskGroupPostProcessor(f.ChasmRegistry),
313 > )
314 }
315
316 > func getOutbountQueueProcessorMetricsHandler(handler metrics.Handler) metrics.Handler { outbound_queue_factory.go
317 > return handler.WithTags(metrics.OperationTag(metrics.OperationOutboundQueueProcessorScope))
318 > }
319
320 func StateMachineTask(smRegistry *hsm.Registry, task tasks.Task) (hsm.Ref, hsm.Task, error) {
364 }
365
366 > func outboundTaskGroupPostProcessor(registry *chasm.Registry) func([]tasks.Task) { outbound_queue_factory.go
367 > if registry == nil {
368 return nil
369 }
370 > return func(taskSlice []tasks.Task) { outbound_queue_factory.go
371 > for _, t := range taskSlice {
372 if ct, ok := t.(*tasks.ChasmTask); ok {
373 if rt, ok := registry.TaskByID(ct.Info.GetTypeId()); ok {
go.temporal.io/server/common/metrics/tally_metrics_handler.go 148 covered LOC · 43 ranges

Open complete file

37 }
38
39 > func newSharedScopeCache(maxSize int) *sharedScopeCache { tally_metrics_handler.go
40 > return &sharedScopeCache{
41 > maxSize: maxSize,
42 > scopes: make(map[string]tally.Scope),
43 > handlers: make(map[string]*tallyMetricsHandler),
44 > }
45 > }
46
47 > func (c *sharedScopeCache) loadOrStoreScope(key string, create func() tally.Scope) tally.Scope { tally_metrics_handler.go
48 > c.mu.RLock()
49 > if s, ok := c.scopes[key]; ok {
50 > c.mu.RUnlock() tally_metrics_handler.go
51 > return s
52 > }
53 > c.mu.RUnlock() tally_metrics_handler.go
54 >
55 > s := create()
56 >
57 > c.mu.Lock()
58 > defer c.mu.Unlock()
59 > // Double-check: another goroutine may have inserted while we were creating.
60 > if existing, ok := c.scopes[key]; ok {
61 return existing
62 }
63 > if len(c.scopes) >= c.maxSize { tally_metrics_handler.go
64 clear(c.scopes)
65 }
66 > c.scopes[key] = s tally_metrics_handler.go
67 > return s
68 }
69
70 > func (c *sharedScopeCache) loadOrStoreHandler(key string, create func() *tallyMetricsHandler) *tallyMetricsHandler { tally_metrics_handler.go
71 > c.mu.RLock()
72 > if h, ok := c.handlers[key]; ok {
73 > c.mu.RUnlock() tally_metrics_handler.go
74 > return h
75 > }
76 > c.mu.RUnlock() tally_metrics_handler.go
77 >
78 > h := create()
79 >
80 > c.mu.Lock()
81 > defer c.mu.Unlock()
82 > // Double-check: another goroutine may have inserted while we were creating.
83 > if existing, ok := c.handlers[key]; ok {
84 return existing
85 }
86 > if len(c.handlers) >= c.maxSize { tally_metrics_handler.go
87 clear(c.handlers)
88 }
89 > c.handlers[key] = h tally_metrics_handler.go
90 > return h
91 }
92
109 var _ Handler = (*tallyMetricsHandler)(nil)
110
111 > func NewTallyMetricsHandler(cfg ClientConfig, scope tally.Scope) *tallyMetricsHandler { tally_metrics_handler.go
112 > perUnitBuckets := make(map[MetricUnit]tally.Buckets)
113 >
114 > for unit, boundariesList := range cfg.PerUnitHistogramBoundaries {
115 > perUnitBuckets[MetricUnit(unit)] = tally.ValueBuckets(boundariesList) tally_metrics_handler.go
116 > }
117
118 > maxSize := cfg.TagsCacheMaxSize tally_metrics_handler.go
119 > if maxSize <= 0 {
120 > maxSize = defaultTagsCacheMaxSize tally_metrics_handler.go
121 > }
122
123 > return &tallyMetricsHandler{ tally_metrics_handler.go
124 > scope: scope,
125 > perUnitBuckets: perUnitBuckets,
126 > excludeTags: configExcludeTags(cfg),
127 > cache: newSharedScopeCache(maxSize),
128 > scopeKey: "",
129 > }
130 }
131
132 // tagsCacheKey builds a compact string key from a tag slice for use as a
133 // map lookup key.
134 > func tagsCacheKey(tags []Tag) string { tally_metrics_handler.go
135 > size := 0
136 > for i := range tags {
137 > size += len(tags[i].Key) + len(tags[i].Value) + 2*binary.MaxVarintLen64
138 > }
139 > var sb strings.Builder
140 > sb.Grow(size)
141 > for _, t := range tags {
142 > appendCacheKeyPart(&sb, t.Key)
143 > appendCacheKeyPart(&sb, t.Value)
144 > }
145 > return sb.String()
146 }
147
148 > func appendCacheKeyPart(sb *strings.Builder, value string) { tally_metrics_handler.go
149 > var lenBuf [binary.MaxVarintLen64]byte
150 > n := binary.PutUvarint(lenBuf[:], uint64(len(value)))
151 > _, _ = sb.Write(lenBuf[:n])
152 > sb.WriteString(value)
153 > }
154
155 // WithTags creates a new MetricProvider with provided []Tag
156 // Tags are merged with registered Tags from the source MetricsHandler.
157 // Handlers are cached by tag combination so repeated calls avoid allocations.
158 > func (tmh *tallyMetricsHandler) WithTags(tags ...Tag) Handler { tally_metrics_handler.go
159 > if len(tags) == 0 {
160 return tmh
161 }
162 > normalizedKey := tagsCacheKey(normalizeTagsForCaching(tags, tmh.excludeTags)) tally_metrics_handler.go
163 > key := tmh.scopeKey + normalizedKey
164 > return tmh.cache.loadOrStoreHandler(key, func() *tallyMetricsHandler {
165 > return &tallyMetricsHandler{
166 > scope: tmh.scope.Tagged(tagsToMap(tags, tmh.excludeTags)),
167 > perUnitBuckets: tmh.perUnitBuckets,
168 > excludeTags: tmh.excludeTags,
169 > cache: tmh.cache,
170 > scopeKey: key,
171 > }
172 > })
173 }
174
178 // excludeTags before cache key computation so that different raw values which
179 // map to the same excluded placeholder share a single cache entry.
180 > func (tmh *tallyMetricsHandler) cachedTaggedScope(tags []Tag) tally.Scope { tally_metrics_handler.go
181 > if len(tags) == 0 {
182 > return tmh.scope tally_metrics_handler.go
183 > }
184 > key := tmh.scopeKey + tagsCacheKey(normalizeTagsForCaching(tags, tmh.excludeTags)) tally_metrics_handler.go
185 > return tmh.cache.loadOrStoreScope(key, func() tally.Scope {
186 > return tmh.scope.Tagged(tagsToMap(tags, tmh.excludeTags))
187 > })
188 }
189
190 // normalizeTag applies excludeTags substitution to a single tag.
191 // Returns the (possibly modified) tag and whether it was normalized.
192 > func normalizeTag(t Tag, excl excludeTags) (Tag, bool) { tally_metrics_handler.go
193 > if vals, ok := excl[t.Key]; ok {
194 if _, ok := vals[t.Value]; !ok {
195 return Tag{Key: t.Key, Value: tagExcludedValue}, true
196 }
197 }
198 > return t, false tally_metrics_handler.go
199 }
200
202 // canonical tag values for cache key computation. Returns the original slice
203 // unchanged if no tags need normalization (zero-alloc fast path).
204 > func normalizeTagsForCaching(tags []Tag, excl excludeTags) []Tag { tally_metrics_handler.go
205 > if len(excl) == 0 {
206 > return tags tally_metrics_handler.go
207 > }
208 var normalized []Tag
209 for i, t := range tags {
223
224 // Counter obtains a counter for the given name.
225 > func (tmh *tallyMetricsHandler) Counter(counter string) CounterIface { tally_metrics_handler.go
226 > if v, ok := tmh.counters.Load(counter); ok {
227 > return v.(CounterIface) //nolint:revive // type-safe: only CounterIface is stored tally_metrics_handler.go
228 > }
229 > c := CounterFunc(func(i int64, t ...Tag) { tally_metrics_handler.go
230 > tmh.cachedTaggedScope(t).Counter(counter).Inc(i)
231 > })
232 > actual, _ := tmh.counters.LoadOrStore(counter, c)
233 > return actual.(CounterIface) //nolint:revive // type-safe: only CounterIface is stored
234 }
235
236 // Gauge obtains a gauge for the given name.
237 > func (tmh *tallyMetricsHandler) Gauge(gauge string) GaugeIface { tally_metrics_handler.go
238 > if v, ok := tmh.gauges.Load(gauge); ok {
239 > return v.(GaugeIface) //nolint:revive // type-safe: only GaugeIface is stored tally_metrics_handler.go
240 > }
241 > g := GaugeFunc(func(f float64, t ...Tag) { tally_metrics_handler.go
242 > tmh.cachedTaggedScope(t).Gauge(gauge).Update(f)
243 > })
244 > actual, _ := tmh.gauges.LoadOrStore(gauge, g)
245 > return actual.(GaugeIface) //nolint:revive // type-safe: only GaugeIface is stored
246 }
247
248 // Timer obtains a timer for the given name.
249 > func (tmh *tallyMetricsHandler) Timer(timer string) TimerIface { tally_metrics_handler.go
250 > if v, ok := tmh.timers.Load(timer); ok {
251 > return v.(TimerIface) //nolint:revive // type-safe: only TimerIface is stored tally_metrics_handler.go
252 > }
253 > ti := TimerFunc(func(d time.Duration, t ...Tag) { tally_metrics_handler.go
254 > tmh.cachedTaggedScope(t).Timer(timer).Record(d)
255 > })
256 > actual, _ := tmh.timers.LoadOrStore(timer, ti)
257 > return actual.(TimerIface) //nolint:revive // type-safe: only TimerIface is stored
258 }
259
260 // Histogram obtains a histogram for the given name.
261 > func (tmh *tallyMetricsHandler) Histogram(histogram string, unit MetricUnit) HistogramIface { tally_metrics_handler.go
262 > key := histogramCacheKey{name: histogram, unit: unit}
263 > if v, ok := tmh.histograms.Load(key); ok {
264 return v.(HistogramIface) //nolint:revive // type-safe: only HistogramIface is stored
265 }
266 > h := HistogramFunc(func(i int64, t ...Tag) { tally_metrics_handler.go
267 > tmh.cachedTaggedScope(t).Histogram(histogram, tmh.perUnitBuckets[unit]).RecordValue(float64(i)) tally_metrics_handler.go
268 > })
269 > actual, _ := tmh.histograms.LoadOrStore(key, h) tally_metrics_handler.go
270 > return actual.(HistogramIface) //nolint:revive // type-safe: only HistogramIface is stored
271 }
272
273 > func (*tallyMetricsHandler) Stop(log.Logger) {} tally_metrics_handler.go
274
275 func (*tallyMetricsHandler) Close() error {
281 }
282
283 > func tagsToMap(t1 []Tag, e excludeTags) map[string]string { tally_metrics_handler.go
284 > if len(t1) == 0 {
285 return nil
286 }
287
288 > m := make(map[string]string, len(t1)) tally_metrics_handler.go
289 > for i := range t1 {
290 > nt, _ := normalizeTag(t1[i], e)
291 > m[nt.Key] = nt.Value
292 > }
293 > return m
294 }
go.temporal.io/server/service/history/replication/fx.go 141 covered LOC · 22 ranges

Open complete file

42 var Module = fx.Provide(
43 NewTaskFetcherFactory,
44 > func(m persistence.ExecutionManager) ExecutionManager { fx.go
45 > return m
46 > },
47 nsreplication.NewNoopDataMerger,
48 nsreplication.NewDefaultAdmitter,
51 ServerSchedulerRateLimiterProvider,
52 PersistenceRateLimiterProvider,
53 > func(serializer serialization.Serializer) TaskSerializer { fx.go
54 > return serializer
55 > },
56 replicationTaskConverterFactoryProvider,
57 replicationTaskExecutorProvider,
86 metricsHandler metrics.Handler,
87 testHooks testhooks.TestHooks,
88 > ) EagerNamespaceRefresher { fx.go
89 > return NewEagerNamespaceRefresher(
90 > metadataManager,
91 > namespaceRegistry,
92 > logger,
93 > clientBean,
94 > nsreplication.NewTaskExecutor(
95 > clusterMetadata.GetCurrentClusterName(),
96 > metadataManager,
97 > dataMerger,
98 > admitter,
99 > logger,
100 > testHooks,
101 > ),
102 > clusterMetadata.GetCurrentClusterName(),
103 > metricsHandler,
104 > )
105 > }
106
107 func replicationTaskConverterFactoryProvider(
108 config *configs.Config,
109 replicationTaskSerializer TaskSerializer,
110 > ) SourceTaskConverterProvider { fx.go
111 > return func(
112 > historyEngine historyi.Engine,
113 > shardContext historyi.ShardContext,
114 > clientClusterName string,
115 > serializer serialization.Serializer,
116 > ) SourceTaskConverter {
117 return NewSourceTaskConverter(
118 historyEngine,
124 }
125
126 > func replicationTaskExecutorProvider() TaskExecutorProvider { fx.go
127 > return func(params TaskExecutorParams) TaskExecutor {
128 return NewTaskExecutor(
129 params.RemoteCluster,
141 queueFactory ctasks.SequentialTaskQueueFactory[TrackableExecutableTask],
142 lc fx.Lifecycle,
143 > ) ctasks.Scheduler[TrackableExecutableTask] { fx.go
144 > // SequentialScheduler has panic wrapper when executing task,
145 > // if changing the executor, please make sure other executor has panic wrapper
146 > scheduler := ctasks.NewSequentialScheduler[TrackableExecutableTask](
147 > &ctasks.SequentialSchedulerOptions{
148 > QueueSize: config.ReplicationProcessorSchedulerQueueSize(),
149 > WorkerCount: config.ReplicationProcessorSchedulerWorkerCount,
150 > },
151 > WorkflowKeyHashFn,
152 > queueFactory,
153 > logger,
154 > )
155 > taskChannelKeyFn := func(e TrackableExecutableTask) ClusterChannelKey {
156 return ClusterChannelKey{
157 ClusterName: e.SourceClusterName(),
158 }
159 }
160 > channelWeightFn := func(key ClusterChannelKey) int { fx.go
161 return 1
162 }
163 // This creates a per cluster channel.
164 // They share the same weight so it just does a round-robin on all clusters' tasks.
165 > rrScheduler := ctasks.NewInterleavedWeightedRoundRobinScheduler( fx.go
166 > ctasks.InterleavedWeightedRoundRobinSchedulerOptions[TrackableExecutableTask, ClusterChannelKey]{
167 > TaskChannelKeyFn: taskChannelKeyFn,
168 > ChannelWeightFn: channelWeightFn,
169 > },
170 > scheduler,
171 > logger,
172 > )
173 > lc.Append(fx.StartStopHook(rrScheduler.Start, rrScheduler.Stop))
174 > return rrScheduler
175 }
176
183 metricsHandler metrics.Handler,
184 lc fx.Lifecycle,
185 > ) ctasks.Scheduler[TrackableExecutableTask] { fx.go
186 > // P-way parallelism for executions of the same workflow (per ReplicationLowPriorityTaskParallelism)
187 > // is modeled as P distinct per-namespace-workflow queue IDs. We bucket by execution (RunID) so all
188 > // low-priority tasks for one execution share a queue; the third field stores the slot index, not
189 > // the run UUID.
190 > queueFactory := func(task TrackableExecutableTask) ctasks.SequentialTaskQueue[TrackableExecutableTask] {
191 item := task.QueueID()
192 workflowKey, ok := item.(definition.WorkflowKey)
204 // SequentialScheduler has panic wrapper when executing task,
205 // if changing the executor, please make sure other executor has panic wrapper
206 > scheduler := ctasks.NewSequentialScheduler[TrackableExecutableTask]( fx.go
207 > &ctasks.SequentialSchedulerOptions{
208 > QueueSize: config.ReplicationProcessorSchedulerQueueSize(),
209 > WorkerCount: config.ReplicationLowPriorityProcessorSchedulerWorkerCount,
210 > },
211 > WorkflowKeyHashFn,
212 > queueFactory,
213 > logger,
214 > )
215 > taskChannelKeyFn := func(e TrackableExecutableTask) ClusterChannelKey {
216 return ClusterChannelKey{
217 ClusterName: e.SourceClusterName(),
218 }
219 }
220 > channelWeightFn := func(key ClusterChannelKey) int { fx.go
221 return 1
222 }
223 > taskQuotaRequestFn := func(t TrackableExecutableTask) quotas.Request { fx.go
224 var taskType string
225 var nsName namespace.Name
245 "")
246 }
247 > taskMetricsTagsFn := func(t TrackableExecutableTask) []metrics.Tag { fx.go
248 replicationTask := t.ReplicationTask()
249 var taskType string
268 // This creates a per cluster channel.
269 // They share the same weight so it just does a round-robin on all clusters' tasks.
270 > rrScheduler := ctasks.NewInterleavedWeightedRoundRobinScheduler( fx.go
271 > ctasks.InterleavedWeightedRoundRobinSchedulerOptions[TrackableExecutableTask, ClusterChannelKey]{
272 > TaskChannelKeyFn: taskChannelKeyFn,
273 > ChannelWeightFn: channelWeightFn,
274 > },
275 > scheduler,
276 > logger,
277 > )
278 > ts := ctasks.NewRateLimitedScheduler[TrackableExecutableTask](
279 > rrScheduler,
280 > rateLimiter,
281 > timeSource,
282 > taskQuotaRequestFn,
283 > taskMetricsTagsFn,
284 > ctasks.RateLimitedSchedulerOptions{
285 > Enabled: config.ReplicationEnableRateLimit,
286 > EnableShadowMode: config.ReplicationEnableRateLimitShadowMode,
287 > },
288 > logger,
289 > metricsHandler,
290 > )
291 > lc.Append(fx.StartStopHook(ts.Start, ts.Stop))
292 > return ts
293 }
294
297 metricsHandler metrics.Handler,
298 config *configs.Config,
299 > ) ctasks.SequentialTaskQueueFactory[TrackableExecutableTask] { fx.go
300 > return func(task TrackableExecutableTask) ctasks.SequentialTaskQueue[TrackableExecutableTask] {
301 if config.EnableReplicationTaskBatching() {
302 return NewSequentialBatchableTaskQueue(task, nil, logger, metricsHandler)
315 func executableTaskConverterProvider(
316 processToolBox ProcessToolBox,
317 > ) ExecutableTaskConverter { fx.go
318 > return NewExecutableTaskConverter(processToolBox)
319 > }
320
321 func streamReceiverMonitorProvider(
322 processToolBox ProcessToolBox,
323 taskConverter ExecutableTaskConverter,
324 > ) StreamReceiverMonitor { fx.go
325 > return NewStreamReceiverMonitor(
326 > processToolBox,
327 > taskConverter,
328 > processToolBox.Config.EnableReplicationStream(),
329 > )
330 > }
331
332 func resendHandlerProvider(
340 logger log.Logger,
341 importer eventhandler.EventImporter,
342 > ) eventhandler.ResendHandler { fx.go
343 > return eventhandler.NewResendHandler(
344 > namespaceRegistry,
345 > clientBean,
346 > serializer,
347 > clusterMetadata,
348 > func(ctx context.Context, namespaceId namespace.ID, workflowId string) (historyi.Engine, error) {
349 shardContext, err := shardController.GetShardByNamespaceWorkflow(
350 namespaceId,
368 serializer serialization.Serializer,
369 logger log.Logger,
370 > ) eventhandler.EventImporter { fx.go
371 > return eventhandler.NewEventImporter(
372 > historyFetcher,
373 > func(ctx context.Context, namespaceId namespace.ID, workflowId string) (historyi.Engine, error) {
374 shardContext, err := shardController.GetShardByNamespaceWorkflow(
375 namespaceId,
390 replicationTaskSerializer TaskSerializer,
391 clusterMetadata cluster.Metadata,
392 > ) *DLQWriterAdapter { fx.go
393 > return NewDLQWriterAdapter(dlqWriter, replicationTaskSerializer, clusterMetadata.GetCurrentClusterName())
394 > }
395
396 func historyEventsHandlerProvider(
399 shardController shard.Controller,
400 logger log.Logger,
401 > ) eventhandler.HistoryEventsHandler { fx.go
402 > return eventhandler.NewHistoryEventsHandler(
403 > clusterMetadata,
404 > importer,
405 > shardController,
406 > logger,
407 > )
408 > }
409
410 func historyPaginatedFetcherProvider(
413 serializer serialization.Serializer,
414 logger log.Logger,
415 > ) eventhandler.HistoryPaginatedFetcher { fx.go
416 > return eventhandler.NewHistoryPaginatedFetcher(
417 > namespaceRegistry,
418 > clientBean,
419 > serializer,
420 > logger,
421 > )
422 > }
go.temporal.io/server/common/persistence/client/factory.go 140 covered LOC · 43 ranges

Open complete file

86 enableDataLossMetrics EnableDataLossMetrics,
87 enableBestEffortDeleteTasksOnWorkflowUpdate EnableBestEffortDeleteTasksOnWorkflowUpdate,
88 > ) Factory { factory.go
89 > factory := &factoryImpl{
90 > dataStoreFactory: dataStoreFactory,
91 > config: cfg,
92 > serializer: serializer,
93 > eventBlobCache: eventBlobCache,
94 > metricsHandler: metricsHandler,
95 > logger: logger,
96 > clusterName: clusterName,
97 > systemRateLimiter: systemRateLimiter,
98 > namespaceRateLimiter: namespaceRateLimiter,
99 > shardRateLimiter: shardRateLimiter,
100 > healthSignals: healthSignals,
101 > enableDataLossMetrics: dynamicconfig.BoolPropertyFn(enableDataLossMetrics),
102 > enableBestEffortDeleteTasksOnWorkflowUpdate: dynamicconfig.BoolPropertyFn(enableBestEffortDeleteTasksOnWorkflowUpdate),
103 > }
104 > factory.initDependencies()
105 > return factory
106 > }
107
108 // NewTaskManager returns a new task manager
109 > func (f *factoryImpl) NewTaskManager() (persistence.TaskManager, error) { factory.go
110 > taskStore, err := f.dataStoreFactory.NewTaskStore()
111 > if err != nil {
112 return nil, err
113 }
114 > result := persistence.NewTaskManager(taskStore, f.serializer) factory.go
115 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
116 > result = persistence.NewTaskPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
117 > }
118 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
119 > result = persistence.NewTaskPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
120 > }
121 > result = persistence.NewTaskPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
122 > return result, nil
123 }
124
125 // NewFairTaskManager returns a new task fairness manager
126 > func (f *factoryImpl) NewFairTaskManager() (persistence.FairTaskManager, error) { factory.go
127 > taskStore, err := f.dataStoreFactory.NewFairTaskStore()
128 > if err != nil {
129 return nil, err
130 }
131 > result := persistence.NewTaskManager(taskStore, f.serializer) factory.go
132 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
133 > result = persistence.NewTaskPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
134 > }
135 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
136 > result = persistence.NewTaskPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
137 > }
138 > result = persistence.NewTaskPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
139 > return result, nil
140 }
141
142 // NewShardManager returns a new shard manager
143 > func (f *factoryImpl) NewShardManager() (persistence.ShardManager, error) { factory.go
144 > shardStore, err := f.dataStoreFactory.NewShardStore()
145 > if err != nil {
146 return nil, err
147 }
148
149 > result := persistence.NewShardManager(shardStore, f.serializer) factory.go
150 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
151 > result = persistence.NewShardPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
152 > }
153 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
154 > result = persistence.NewShardPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
155 > }
156 > result = persistence.NewShardPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
157 > return result, nil
158 }
159
160 // NewMetadataManager returns a new metadata manager
161 > func (f *factoryImpl) NewMetadataManager() (persistence.MetadataManager, error) { factory.go
162 > store, err := f.dataStoreFactory.NewMetadataStore()
163 > if err != nil {
164 return nil, err
165 }
166
167 > result := persistence.NewMetadataManagerImpl(store, f.serializer, f.logger, f.clusterName) factory.go
168 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
169 > result = persistence.NewMetadataPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
170 > }
171 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
172 > result = persistence.NewMetadataPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
173 > }
174 > result = persistence.NewMetadataPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
175 > return result, nil
176 }
177
178 // NewClusterMetadataManager returns a new cluster metadata manager
179 > func (f *factoryImpl) NewClusterMetadataManager() (persistence.ClusterMetadataManager, error) { factory.go
180 > store, err := f.dataStoreFactory.NewClusterMetadataStore()
181 > if err != nil {
182 return nil, err
183 }
184
185 > result := persistence.NewClusterMetadataManagerImpl(store, f.serializer, f.clusterName, f.logger) factory.go
186 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
187 > result = persistence.NewClusterMetadataPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
188 > }
189 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
190 > result = persistence.NewClusterMetadataPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
191 > }
192 > result = persistence.NewClusterMetadataPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
193 > return result, nil
194 }
195
196 // NewExecutionManager returns a new execution manager
197 > func (f *factoryImpl) NewExecutionManager() (persistence.ExecutionManager, error) { factory.go
198 > store, err := f.dataStoreFactory.NewExecutionStore()
199 > if err != nil {
200 return nil, err
201 }
202
203 > result := persistence.NewExecutionManager( factory.go
204 > store,
205 > f.serializer,
206 > f.eventBlobCache,
207 > f.logger,
208 > f.config.TransactionSizeLimit,
209 > f.enableBestEffortDeleteTasksOnWorkflowUpdate,
210 > )
211 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
212 > result = persistence.NewExecutionPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
213 > }
214 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
215 > result = persistence.NewExecutionPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
216 > }
217 > result = persistence.NewExecutionPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
218 > return result, nil
219 }
220
221 > func (f *factoryImpl) NewNamespaceReplicationQueue() (persistence.NamespaceReplicationQueue, error) { factory.go
222 > result, err := f.dataStoreFactory.NewQueue(persistence.NamespaceReplicationQueueType)
223 > if err != nil {
224 return nil, err
225 }
226
227 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil { factory.go
228 > result = persistence.NewQueuePersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
229 > }
230 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
231 > result = persistence.NewQueuePersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
232 > }
233 > result = persistence.NewQueuePersistenceRetryableClient(result, namespaceQueueRetryPolicy, IsNamespaceQueueTransientError)
234 > return persistence.NewNamespaceReplicationQueue(result, f.serializer, f.clusterName, f.metricsHandler, f.logger)
235 }
236
237 > func (f *factoryImpl) NewHistoryTaskQueueManager() (persistence.HistoryTaskQueueManager, error) { factory.go
238 > q, err := f.dataStoreFactory.NewQueueV2()
239 > if err != nil {
240 return nil, err
241 }
242 > return persistence.NewHistoryTaskQueueManager(q, f.serializer), nil factory.go
243 }
244
245 > func (f *factoryImpl) NewNexusEndpointManager() (persistence.NexusEndpointManager, error) { factory.go
246 > store, err := f.dataStoreFactory.NewNexusEndpointStore()
247 > if err != nil {
248 return nil, err
249 }
250
251 > result := persistence.NewNexusEndpointManager(store, f.serializer, f.logger) factory.go
252 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
253 > result = persistence.NewNexusEndpointPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
254 > }
255 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
256 > result = persistence.NewNexusEndpointPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
257 > }
258 > result = persistence.NewNexusEndpointPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
259 > return result, nil
260 }
261
262 // Close closes this factory
263 > func (f *factoryImpl) Close() { factory.go
264 > f.dataStoreFactory.Close()
265 > if f.healthSignals != nil {
266 > f.healthSignals.Stop()
267 > }
268 }
269
270 > func IsPersistenceTransientError(err error) bool { factory.go
271 > switch err.(type) {
272 // we retry on DataLoss errors because persistence layer is sometimes unreliable when we immediately read-after-write
273 case *serviceerror.Unavailable, *serviceerror.DataLoss:
275 }
276
277 > return false factory.go
278 }
279
287 }
288
289 > func (f *factoryImpl) initDependencies() { factory.go
290 > if f.metricsHandler == nil && f.healthSignals == nil {
291 return
292 }
293
294 > if f.metricsHandler == nil { factory.go
295 f.metricsHandler = metrics.NoopMetricsHandler
296 }
297 > if f.healthSignals == nil { factory.go
298 > f.healthSignals = persistence.NoopHealthSignalAggregator factory.go
299 > }
300 > f.healthSignals.Start() factory.go
301 }
go.temporal.io/server/service/history/queues/queue_scheduled.go 137 covered LOC · 30 ranges

Open complete file

51 logger log.Logger,
52 metricsHandler metrics.Handler,
53 > ) *scheduledQueue { queue_scheduled.go
54 > paginationFnProvider := func(r Range) collection.PaginationFn[tasks.Task] {
55 > return func(paginationToken []byte) ([]tasks.Task, []byte, error) { queue_scheduled.go
56 > ctx, cancel := newQueueIOContext()
57 > defer cancel()
58 >
59 > request := &persistence.GetHistoryTasksRequest{
60 > ShardID: shard.GetShardID(),
61 > TaskCategory: category,
62 > InclusiveMinTaskKey: tasks.NewKey(r.InclusiveMin.FireTime, 0),
63 > ExclusiveMaxTaskKey: tasks.NewKey(
64 > r.ExclusiveMax.FireTime.Add(common.ScheduledTaskMinPrecision),
65 > 0,
66 > ),
67 > BatchSize: options.BatchSize(),
68 > NextPageToken: paginationToken,
69 > }
70 >
71 > resp, err := shard.GetHistoryTasks(ctx, request)
72 > if err != nil {
73 return nil, nil, err
74 }
75
76 > for len(resp.Tasks) > 0 && !r.ContainsKey(resp.Tasks[0].GetKey()) { queue_scheduled.go
77 resp.Tasks = resp.Tasks[1:]
78 }
79
80 > for len(resp.Tasks) > 0 && !r.ContainsKey(resp.Tasks[len(resp.Tasks)-1].GetKey()) { queue_scheduled.go
81 resp.Tasks = resp.Tasks[:len(resp.Tasks)-1]
82 resp.NextPageToken = nil
83 }
84
85 > return resp.Tasks, resp.NextPageToken, nil queue_scheduled.go
86 }
87 }
88
89 > lookAheadCh := make(chan struct{}, 1) queue_scheduled.go
90 > readerCompletionFn := func(readerID int64) {
91 > if readerID != DefaultReaderId { queue_scheduled.go
92 return
93 }
94
95 > select { queue_scheduled.go
96 > case lookAheadCh <- struct{}{}:
97 default:
98 }
99 }
100
101 > return &scheduledQueue{ queue_scheduled.go
102 > queueBase: newQueueBase(
103 > shard,
104 > category,
105 > paginationFnProvider,
106 > scheduler,
107 > rescheduler,
108 > executableFactory,
109 > options,
110 > hostRateLimiter,
111 > readerCompletionFn,
112 > GrouperNamespaceID{},
113 > logger,
114 > metricsHandler,
115 > ),
116 >
117 > timerGate: timer.NewLocalGate(shard.GetTimeSource()),
118 > newTimerCh: make(chan struct{}, 1),
119 >
120 > lookAheadCh: lookAheadCh,
121 > lookAheadRateLimitRequest: newReaderRequest(DefaultReaderId),
122 > }
123 }
124
125 > func (p *scheduledQueue) Start() { queue_scheduled.go
126 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
127 return
128 }
129
130 > p.logger.Info("", tag.LifeCycleStarting) queue_scheduled.go
131 > defer p.logger.Info("", tag.LifeCycleStarted)
132 >
133 > p.queueBase.Start()
134 >
135 > p.shutdownWG.Add(1)
136 > go p.processEventLoop()
137 >
138 > p.notify(time.Time{})
139 }
140
141 > func (p *scheduledQueue) Stop() { queue_scheduled.go
142 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
143 return
144 }
145
146 > p.logger.Info("", tag.LifeCycleStopping) queue_scheduled.go
147 > defer p.logger.Info("", tag.LifeCycleStopped)
148 >
149 > close(p.shutdownCh)
150 > p.timerGate.Close()
151 >
152 > if success := common.AwaitWaitGroup(&p.shutdownWG, time.Minute); !success {
153 p.logger.Warn("", tag.LifeCycleStopTimedout)
154 }
155
156 > p.queueBase.Stop() queue_scheduled.go
157 }
158
159 > func (p *scheduledQueue) NotifyNewTasks(tasks []tasks.Task) { queue_scheduled.go
160 > if len(tasks) == 0 {
161 return
162 }
163
164 > newTime := tasks[0].GetVisibilityTime() queue_scheduled.go
165 > for _, task := range tasks {
166 > ts := task.GetVisibilityTime()
167 > if ts.Before(newTime) {
168 newTime = ts
169 }
170 }
171
172 > p.notify(newTime) queue_scheduled.go
173 }
174
175 > func (p *scheduledQueue) processEventLoop() { queue_scheduled.go
176 > defer p.shutdownWG.Done()
177 >
178 > for {
179 > select {
180 case <-p.shutdownCh:
181 return
182 > default: queue_scheduled.go
183 }
184
185 > select { queue_scheduled.go
186 > case <-p.shutdownCh: queue_scheduled.go
187 > return
188 > case <-p.newTimerCh: queue_scheduled.go
189 > metrics.NewTimerNotifyCounter.With(p.metricsHandler).Record(1)
190 > p.processNewTime()
191 > case <-p.lookAheadCh:
192 > p.lookAheadTask()
193 > case <-p.timerGate.FireCh():
194 > p.processNewRange()
195 case <-p.checkpointTimer.C:
196 p.checkpoint()
201 }
202
203 > func (p *scheduledQueue) notify(newTime time.Time) { queue_scheduled.go
204 > p.newTimeLock.Lock()
205 > defer p.newTimeLock.Unlock()
206 >
207 > if !p.newTime.IsZero() && !newTime.Before(p.newTime) {
208 return
209 }
210
211 > p.newTime = newTime queue_scheduled.go
212 > select {
213 > case p.newTimerCh <- struct{}{}:
214 > default: queue_scheduled.go
215 }
216 }
217
218 > func (p *scheduledQueue) processNewTime() { queue_scheduled.go
219 > p.newTimeLock.Lock()
220 > newTime := p.newTime
221 > p.newTime = time.Time{}
222 > p.newTimeLock.Unlock()
223 >
224 > p.timerGate.Update(newTime)
225 > }
226
227 > func (p *scheduledQueue) lookAheadTask() { queue_scheduled.go
228 > rateLimitCtx, rateLimitCancel := context.WithTimeout(context.Background(), lookAheadRateLimitDelay)
229 > rateLimitErr := p.readerRateLimiter.Wait(rateLimitCtx, p.lookAheadRateLimitRequest)
230 > rateLimitCancel()
231 > if rateLimitErr != nil {
232 deadline, _ := rateLimitCtx.Deadline()
233 p.timerGate.Update(deadline)
235 }
236
237 > lookAheadMinTime := p.nonReadableScope.Range.InclusiveMin.FireTime queue_scheduled.go
238 > lookAheadMaxTime := lookAheadMinTime.Add(backoff.Jitter(
239 > p.options.MaxPollInterval(),
240 > p.options.MaxPollIntervalJitterCoefficient(),
241 > ))
242 >
243 > ctx, cancel := newQueueIOContext()
244 > defer cancel()
245 >
246 > request := &persistence.GetHistoryTasksRequest{
247 > ShardID: p.shard.GetShardID(),
248 > TaskCategory: p.category,
249 > InclusiveMinTaskKey: tasks.NewKey(lookAheadMinTime, 0),
250 > ExclusiveMaxTaskKey: tasks.NewKey(lookAheadMaxTime, 0),
251 > BatchSize: 1,
252 > NextPageToken: nil,
253 > }
254 > response, err := p.shard.GetHistoryTasks(ctx, request)
255 > if err != nil {
256 p.logger.Error("Failed to load look ahead task", tag.Error(err))
257 if common.IsResourceExhausted(err) {
266 }
267
268 > if len(response.Tasks) == 1 { queue_scheduled.go
269 p.timerGate.Update(response.Tasks[0].GetKey().FireTime)
270 return
275 // NOTE: with this we don't need a separate max poll timer, loading will be triggerred
276 // every maxPollInterval + jitter.
277 > p.timerGate.Update(lookAheadMaxTime) queue_scheduled.go
278 }
279
go.temporal.io/server/service/history/queues/queue_base.go 132 covered LOC · 18 ranges

Open complete file

116 logger log.Logger,
117 metricsHandler metrics.Handler,
118 > ) *queueBase { queue_base.go
119 > var readerScopes map[int64][]Scope
120 > var exclusiveReaderHighWatermark tasks.Key
121 > if persistenceState, ok := shard.GetQueueState(category); ok {
122 queueState := FromPersistenceQueueState(persistenceState)
123
124 readerScopes = queueState.readerScopes
125 exclusiveReaderHighWatermark = queueState.exclusiveReaderHighWatermark
126 > } else { queue_base.go
127 > ackLevel := tasks.NewKey(tasks.DefaultFireTime, 0) queue_base.go
128 > if category.Type() == tasks.CategoryTypeImmediate {
129 > // convert to exclusive ack level queue_base.go
130 > ackLevel = ackLevel.Next()
131 > }
132
133 > exclusiveReaderHighWatermark = ackLevel queue_base.go
134 }
135
136 > monitor := newMonitor(category.Type(), shard.GetTimeSource(), &options.MonitorOptions) queue_base.go
137 > readerRateLimiter := newShardReaderRateLimiter(
138 > options.MaxPollRPS,
139 > hostReaderRateLimiter,
140 > int64(options.MaxReaderCount()),
141 > )
142 > readerInitializer := func(readerID int64, slices []Slice) Reader {
143 > readerOptions := options.ReaderOptions // make a copy queue_base.go
144 > if readerID != DefaultReaderId {
145 // non-default reader should not trigger task unloading
146 // otherwise those readers will keep loading, hit pending task count limit, unload, throttle, load, etc...
161 }
162
163 > return NewReader( queue_base.go
164 > readerID,
165 > slices,
166 > &readerOptions,
167 > scheduler,
168 > rescheduler,
169 > shard.GetTimeSource(),
170 > readerRateLimiter,
171 > monitor,
172 > completionFn,
173 > logger,
174 > metricsHandler,
175 > )
176 }
177
178 > exclusiveDeletionHighWatermark := exclusiveReaderHighWatermark queue_base.go
179 > readerGroup := NewReaderGroup(readerInitializer)
180 > for readerID, scopes := range readerScopes {
181 if len(scopes) == 0 {
182 continue
192 }
193
194 > mitigator := newMitigator(readerGroup, monitor, logger, metricsHandler, options.MaxReaderCount, grouper) queue_base.go
195 >
196 > return &queueBase{
197 > shard: shard,
198 >
199 > status: common.DaemonStatusInitialized,
200 > shutdownCh: make(chan struct{}),
201 >
202 > category: category,
203 > options: options,
204 > scheduler: scheduler,
205 > rescheduler: rescheduler,
206 > timeSource: shard.GetTimeSource(),
207 > monitor: monitor,
208 > mitigator: mitigator,
209 > grouper: grouper,
210 > logger: logger,
211 > metricsHandler: metricsHandler,
212 >
213 > paginationFnProvider: paginationFnProvider,
214 > executableFactory: executableFactory,
215 >
216 > lastRangeID: -1, // start from an invalid rangeID
217 > exclusiveDeletionHighWatermark: exclusiveDeletionHighWatermark,
218 > nonReadableScope: NewScope(
219 > NewRange(exclusiveReaderHighWatermark, tasks.MaximumKey),
220 > predicates.Universal[tasks.Task](),
221 > ),
222 > readerRateLimiter: readerRateLimiter,
223 > readerGroup: readerGroup,
224 >
225 > // pollTimer and checkpointTimer are initialized on Start()
226 > checkpointRetrier: backoff.NewRetrier(
227 > createCheckpointRetryPolicy(),
228 > clock.NewRealTimeSource(),
229 > ),
230 >
231 > alertCh: monitor.AlertCh(),
232 > }
233 }
234
235 > func (p *queueBase) Start() { queue_base.go
236 > p.rescheduler.Start()
237 > p.readerGroup.Start()
238 >
239 > p.checkpointTimer = time.NewTimer(backoff.Jitter(
240 > p.options.CheckpointInterval(),
241 > p.options.CheckpointIntervalJitterCoefficient(),
242 > ))
243 > }
244
245 > func (p *queueBase) Stop() { queue_base.go
246 > p.monitor.Close()
247 > p.readerGroup.Stop()
248 > p.rescheduler.Stop()
249 > p.checkpointTimer.Stop()
250 > }
251
252 > func (p *queueBase) Category() tasks.Category { queue_base.go
253 > return p.category
254 > }
255
256 func (p *queueBase) FailoverNamespace(
260 }
261
262 > func (p *queueBase) processNewRange() { queue_base.go
263 > newMaxKey := p.shard.GetQueueExclusiveHighReadWatermark(p.category)
264 >
265 > slices := make([]Slice, 0, 1)
266 > if p.nonReadableScope.CanSplitByRange(newMaxKey) {
267 > var newReadScope Scope
268 > newReadScope, p.nonReadableScope = p.nonReadableScope.SplitByRange(newMaxKey)
269 > slices = append(slices, NewSlice(
270 > p.paginationFnProvider,
271 > p.executableFactory,
272 > p.monitor,
273 > newReadScope,
274 > p.grouper,
275 > p.options.MaxPredicateSize,
276 > p.options.ShrinkPredicateMaxPendingKeys,
277 > p.metricsHandler,
278 > ))
279 > }
280
281 > reader, ok := p.readerGroup.ReaderByID(DefaultReaderId) queue_base.go
282 > if !ok {
283 > p.readerGroup.NewReader(DefaultReaderId, slices...)
284 > return
285 > }
286
287 > if now := p.timeSource.Now(); now.After(p.nextForceNewSliceTime) { queue_base.go
288 > reader.AppendSlices(slices...)
289 > p.nextForceNewSliceTime = now.Add(forceNewSliceDuration)
290 > } else {
291 reader.MergeSlices(slices...)
292 }
446 }
447
448 > func createCheckpointRetryPolicy() backoff.RetryPolicy { queue_base.go
449 > policy := backoff.NewExponentialRetryPolicy(100 * time.Millisecond).
450 > WithMaximumInterval(5 * time.Second).
451 > WithExpirationInterval(backoff.NoInterval)
452 >
453 > return policy
454 > }
455
456 > func newQueueIOContext() (context.Context, context.CancelFunc) { queue_base.go
457 > ctx, cancel := context.WithTimeout(context.Background(), queueIOTimeout)
458 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
459 > return ctx, cancel
460 > }
go.temporal.io/server/common/persistence/visibility/factory.go 131 covered LOC · 12 ranges

Open complete file

56 logger log.Logger,
57 serializer serialization.Serializer,
58 > ) (manager.VisibilityManager, error) { factory.go
59 > visibilityManager, err := newVisibilityManagerFromDataStoreConfig(
60 > persistenceCfg.GetVisibilityStoreConfig(),
61 > persistenceResolver,
62 > customVisibilityStoreFactory,
63 > esProcessorConfig,
64 > searchAttributesProvider,
65 > searchAttributesMapperProvider,
66 > namespaceRegistry,
67 > chasmRegistry,
68 > maxReadQPS,
69 > maxWriteQPS,
70 > operatorRPSRatio,
71 > slowQueryThreshold,
72 > visibilityDisableOrderByClause,
73 > visibilityEnableManualPagination,
74 > visibilityEnableUnifiedQueryConverter,
75 > metricsHandler,
76 > logger,
77 > serializer,
78 > )
79 > if err != nil {
80 return nil, err
81 }
82 > if visibilityManager == nil { factory.go
83 logger.Fatal("invalid config: visibility store must be configured")
84 return nil, nil
85 }
86
87 > secondaryVisibilityManager, err := newVisibilityManagerFromDataStoreConfig( factory.go
88 > persistenceCfg.GetSecondaryVisibilityStoreConfig(),
89 > persistenceResolver,
90 > customVisibilityStoreFactory,
91 > esProcessorConfig,
92 > searchAttributesProvider,
93 > searchAttributesMapperProvider,
94 > namespaceRegistry,
95 > chasmRegistry,
96 > maxReadQPS,
97 > maxWriteQPS,
98 > operatorRPSRatio,
99 > slowQueryThreshold,
100 > visibilityDisableOrderByClause,
101 > visibilityEnableManualPagination,
102 > visibilityEnableUnifiedQueryConverter,
103 > metricsHandler,
104 > logger,
105 > serializer,
106 > )
107 > if err != nil {
108 return nil, err
109 }
110
111 > if secondaryVisibilityManager != nil { factory.go
112 managerSelector := newDefaultManagerSelector(
113 visibilityManager,
124 }
125
126 > return visibilityManager, nil factory.go
127 }
128
139 searchAttributesMapperProvider searchattribute.MapperProvider,
140 chasmRegistry *chasm.Registry,
141 > ) manager.VisibilityManager { factory.go
142 > if visStore == nil {
143 return nil
144 }
145 > logger.Info( factory.go
146 > "creating new visibility manager",
147 > tag.String(visibilityPluginNameTag.Key, visibilityPluginNameTag.Value),
148 > tag.String(visibilityIndexNameTag.Key, visibilityIndexNameTag.Value),
149 > )
150 > var visManager manager.VisibilityManager = newVisibilityManagerImpl(
151 > visStore,
152 > logger,
153 > searchAttributesMapperProvider,
154 > chasmRegistry,
155 > )
156 >
157 > // wrap with rate limiter
158 > visManager = NewVisibilityManagerRateLimited(
159 > visManager,
160 > maxReadQPS,
161 > maxWriteQPS,
162 > operatorRPSRatio,
163 > )
164 > // wrap with metrics client
165 > visManager = NewVisibilityManagerMetrics(
166 > visManager,
167 > metricsHandler,
168 > logger,
169 > slowQueryThreshold,
170 > visibilityPluginNameTag,
171 > visibilityIndexNameTag,
172 > )
173 > return visManager
174 }
175
197 logger log.Logger,
198 serializer serialization.Serializer,
199 > ) (manager.VisibilityManager, error) { factory.go
200 > visStore, err := newVisibilityStoreFromDataStoreConfig(
201 > dsConfig,
202 > persistenceResolver,
203 > customVisibilityStoreFactory,
204 > esProcessorConfig,
205 > searchAttributesProvider,
206 > searchAttributesMapperProvider,
207 > namespaceRegistry,
208 > chasmRegistry,
209 > visibilityDisableOrderByClause,
210 > visibilityEnableManualPagination,
211 > visibilityEnableUnifiedQueryConverter,
212 > metricsHandler,
213 > logger,
214 > serializer,
215 > )
216 > if err != nil {
217 return nil, err
218 }
219 > if visStore == nil { factory.go
220 > return nil, nil
221 > }
222 > return newVisibilityManager(
223 > visStore,
224 > maxReadQPS,
225 > maxWriteQPS,
226 > operatorRPSRatio,
227 > slowQueryThreshold,
228 > metricsHandler,
229 > metrics.VisibilityPluginNameTag(visStore.GetName()),
230 > metrics.VisibilityIndexNameTag(visStore.GetIndexName()),
231 > logger,
232 > searchAttributesMapperProvider,
233 > chasmRegistry,
234 > ), nil
235 }
236
252 logger log.Logger,
253 serializer serialization.Serializer,
254 > ) (store.VisibilityStore, error) { factory.go
255 > var (
256 > visStore store.VisibilityStore
257 > err error
258 > )
259 > if dsConfig.SQL != nil {
260 > visStore, err = sql.NewSQLVisibilityStore(
261 > *dsConfig.SQL,
262 > persistenceResolver,
263 > searchAttributesProvider,
264 > searchAttributesMapperProvider,
265 > chasmRegistry,
266 > visibilityEnableUnifiedQueryConverter,
267 > logger,
268 > metricsHandler,
269 > serializer,
270 > )
271 > } else if dsConfig.Elasticsearch != nil {
272 visStore, err = elasticsearch.NewVisibilityStore(
273 dsConfig.Elasticsearch,
282 logger,
283 )
284 > } else if dsConfig.CustomDataStoreConfig != nil { factory.go
285 if customVisibilityStoreFactory == nil {
286 logger.Fatal("custom visibility store factory must be defined")
298 )
299 }
300 > return visStore, err factory.go
301 }
go.temporal.io/server/service/history/visibility_queue_factory.go 131 covered LOC · 3 ranges

Open complete file

35 func NewVisibilityQueueFactory(
36 params visibilityQueueFactoryParams,
37 > ) QueueFactory { visibility_queue_factory.go
38 > return &visibilityQueueFactory{
39 > visibilityQueueFactoryParams: params,
40 > QueueFactoryBase: QueueFactoryBase{
41 > HostScheduler: queues.NewScheduler(
42 > params.ClusterMetadata.GetCurrentClusterName(),
43 > queues.SchedulerOptions{
44 > WorkerCount: params.Config.VisibilityProcessorSchedulerWorkerCount,
45 > ActiveNamespaceWeights: params.Config.VisibilityProcessorSchedulerActiveRoundRobinWeights,
46 > StandbyNamespaceWeights: params.Config.VisibilityProcessorSchedulerStandbyRoundRobinWeights,
47 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
48 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
49 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
50 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
51 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
52 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
53 > },
54 > },
55 > params.NamespaceRegistry,
56 > params.Logger,
57 > params.MetricsHandler,
58 > params.TimeSource,
59 > ),
60 > HostPriorityAssigner: queues.NewPriorityAssigner(
61 > params.NamespaceRegistry,
62 > params.ClusterMetadata.GetCurrentClusterName(),
63 > ),
64 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
65 > NewHostRateLimiterRateFn(
66 > params.Config.VisibilityProcessorMaxPollHostRPS,
67 > params.Config.PersistenceMaxQPS,
68 > visibilityQueuePersistenceMaxRPSRatio,
69 > ),
70 > int64(params.Config.VisibilityQueueMaxReaderCount()),
71 > ),
72 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueVisibility),
73 > },
74 > }
75 > }
76
77 func (f *visibilityQueueFactory) CreateQueue(
78 shard historyi.ShardContext,
79 > ) queues.Queue { visibility_queue_factory.go
80 > logger := log.With(shard.GetLogger(), tag.ComponentVisibilityQueue)
81 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationVisibilityQueueProcessorScope))
82 >
83 > shardScheduler := queues.NewRateLimitedScheduler(
84 > f.HostScheduler,
85 > queues.RateLimitedSchedulerOptions{
86 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
87 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
88 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
89 > },
90 > f.ClusterMetadata.GetCurrentClusterName(),
91 > f.NamespaceRegistry,
92 > f.SchedulerRateLimiter,
93 > f.TimeSource,
94 > f.ChasmRegistry,
95 > logger,
96 > metricsHandler,
97 > )
98 >
99 > rescheduler := queues.NewRescheduler(
100 > shardScheduler,
101 > shard.GetTimeSource(),
102 > logger,
103 > metricsHandler,
104 > )
105 >
106 > executor := newVisibilityQueueTaskExecutor(
107 > shard,
108 > f.WorkflowCache,
109 > f.VisibilityMgr,
110 > logger,
111 > f.MetricsHandler,
112 > f.Config.VisibilityProcessorEnsureCloseBeforeDelete,
113 > f.Config.VisibilityProcessorEnableCloseWorkflowCleanup,
114 > f.Config.VisibilityProcessorRelocateAttributesMinBlobSize,
115 > f.Config.ExternalPayloadsEnabled,
116 > )
117 > if f.ExecutorWrapper != nil {
118 executor = f.ExecutorWrapper.Wrap(executor)
119 }
120
121 > factory := queues.NewExecutableFactory( visibility_queue_factory.go
122 > executor,
123 > shardScheduler,
124 > rescheduler,
125 > f.HostPriorityAssigner,
126 > shard.GetTimeSource(),
127 > shard.GetNamespaceRegistry(),
128 > shard.GetClusterMetadata(),
129 > f.ChasmRegistry,
130 > queues.GetTaskTypeTagValue,
131 > logger,
132 > metricsHandler,
133 > f.Tracer,
134 > f.DLQWriter,
135 > f.Config.TaskDLQEnabled,
136 > f.Config.TaskDLQUnexpectedErrorAttempts,
137 > f.Config.TaskDLQInternalErrors,
138 > f.Config.TaskDLQErrorPattern,
139 > )
140 > return queues.NewImmediateQueue(
141 > shard,
142 > tasks.CategoryVisibility,
143 > shardScheduler,
144 > rescheduler,
145 > &queues.Options{
146 > ReaderOptions: queues.ReaderOptions{
147 > BatchSize: f.Config.VisibilityTaskBatchSize,
148 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
149 > PollBackoffInterval: f.Config.VisibilityProcessorPollBackoffInterval,
150 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
151 > },
152 > MonitorOptions: queues.MonitorOptions{
153 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
154 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
155 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
156 > },
157 > MaxPollRPS: f.Config.VisibilityProcessorMaxPollRPS,
158 > MaxPollInterval: f.Config.VisibilityProcessorMaxPollInterval,
159 > MaxPollIntervalJitterCoefficient: f.Config.VisibilityProcessorMaxPollIntervalJitterCoefficient,
160 > CheckpointInterval: f.Config.VisibilityProcessorUpdateAckInterval,
161 > CheckpointIntervalJitterCoefficient: f.Config.VisibilityProcessorUpdateAckIntervalJitterCoefficient,
162 > MaxReaderCount: f.Config.VisibilityQueueMaxReaderCount,
163 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
164 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
165 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
166 > },
167 > f.HostReaderRateLimiter,
168 > queues.GrouperNamespaceID{},
169 > logger,
170 > metricsHandler,
171 > factory,
172 > nil, // taskPostProcessor
173 > )
174 }
go.temporal.io/server/service/history/queues/reader.go 128 covered LOC · 39 ranges

Open complete file

88
89 var (
90 > NoopReaderCompletionFn = func(_ int64) {} reader.go
91 )
92
103 logger log.Logger,
104 metricsHandler metrics.Handler,
105 > ) *ReaderImpl { reader.go
106 >
107 > sliceList := list.New()
108 > for _, slice := range slices {
109 > sliceList.PushBack(slice) reader.go
110 > }
111 > monitor.SetSliceCount(readerID, len(slices)) reader.go
112 >
113 > rateLimitContext, rateLimitContextCancel := context.WithCancel(context.Background())
114 > return &ReaderImpl{
115 > readerID: readerID,
116 > options: options,
117 > scheduler: scheduler,
118 > rescheduler: rescheduler,
119 > timeSource: timeSource,
120 > ratelimiter: ratelimiter,
121 > monitor: monitor,
122 > completionFn: completionFn,
123 > logger: log.With(logger, tag.QueueReaderID(readerID)),
124 > metricsHandler: metricsHandler,
125 >
126 > status: common.DaemonStatusInitialized,
127 > shutdownCh: make(chan struct{}),
128 >
129 > slices: sliceList,
130 > nextReadSlice: sliceList.Front(),
131 > notifyCh: make(chan struct{}, 1),
132 >
133 > retrier: backoff.NewRetrier(
134 > common.CreateReadTaskRetryPolicy(),
135 > clock.NewRealTimeSource(),
136 > ),
137 >
138 > rateLimitContext: rateLimitContext,
139 > rateLimitContextCancel: rateLimitContextCancel,
140 > rateLimiterRequest: newReaderRequest(readerID),
141 > }
142 }
143
144 > func (r *ReaderImpl) Start() { reader.go
145 > if !atomic.CompareAndSwapInt32(
146 > &r.status,
147 > common.DaemonStatusInitialized,
148 > common.DaemonStatusStarted,
149 > ) {
150 return
151 }
152
153 > r.shutdownWG.Add(1) reader.go
154 > go r.eventLoop()
155 >
156 > r.notify()
157 >
158 > r.logger.Info("queue reader started", tag.LifeCycleStarted)
159 }
160
161 > func (r *ReaderImpl) Stop() { reader.go
162 > if !atomic.CompareAndSwapInt32(
163 > &r.status,
164 > common.DaemonStatusStarted,
165 > common.DaemonStatusStopped,
166 > ) {
167 return
168 }
169
170 > r.monitor.RemoveReader(r.readerID) reader.go
171 >
172 > close(r.shutdownCh)
173 > r.rateLimitContextCancel()
174 > if success := common.AwaitWaitGroup(&r.shutdownWG, time.Minute); !success {
175 r.logger.Warn("queue reader shutdown timed out waiting for event loop", tag.LifeCycleStopTimedout)
176 }
177 > r.logger.Info("queue reader stopped", tag.LifeCycleStopped) reader.go
178 }
179
271 }
272
273 > func (r *ReaderImpl) AppendSlices(incomingSlices ...Slice) { reader.go
274 > if len(incomingSlices) == 0 {
275 return
276 }
277
278 > validateSlicesOrderedDisjoint(incomingSlices) reader.go
279 > if back := r.slices.Back(); back != nil {
280 > lastSliceRange := back.Value.(Slice).Scope().Range
281 > firstIncomingRange := incomingSlices[0].Scope().Range
282 > if lastSliceRange.ExclusiveMax.CompareTo(firstIncomingRange.InclusiveMin) > 0 {
283 panic(fmt.Sprintf(
284 "Can not append slice to existing list of slices, incoming slice range: %v, existing slice range: %v ",
289 }
290
291 > r.Lock() reader.go
292 > defer r.Unlock()
293 >
294 > for _, incomingSlice := range incomingSlices {
295 > if scope := incomingSlice.Scope(); scope.IsEmpty() {
296 > continue reader.go
297 }
298 r.slices.PushBack(incomingSlice)
299 }
300
301 > r.resetNextReadSliceLocked() reader.go
302 > r.monitor.SetSliceCount(r.readerID, r.slices.Len())
303 }
304
402 }
403
404 > func (r *ReaderImpl) eventLoop() { reader.go
405 > defer func() {
406 > r.shutdownWG.Done() reader.go
407 > }()
408
409 > for { reader.go
410 > // prioritize shutdown
411 > select {
412 case <-r.shutdownCh:
413 return
414 > default: reader.go
415 }
416
417 > select { reader.go
418 > case <-r.shutdownCh: reader.go
419 > return
420 > case <-r.notifyCh: reader.go
421 > r.loadAndSubmitTasks()
422 }
423 }
424 }
425
426 > func (r *ReaderImpl) loadAndSubmitTasks() { reader.go
427 > if err := r.ratelimiter.Wait(r.rateLimitContext, r.rateLimiterRequest); err != nil {
428 if r.rateLimitContext.Err() != nil {
429 return
435 }
436
437 > r.Lock() reader.go
438 > defer r.Unlock()
439 >
440 > if !r.verifyPendingTaskSize() {
441 r.pauseLocked(r.options.PollBackoffInterval())
442 }
443
444 > if r.throttleTimer != nil { reader.go
445 return
446 }
447
448 > if r.nextReadSlice == nil { reader.go
449 r.completionFn(r.readerID)
450 return
451 }
452
453 > loadSlice := r.nextReadSlice.Value.(Slice) reader.go
454 > tasks, err := loadSlice.SelectTasks(r.readerID, r.options.BatchSize())
455 > if err != nil {
456 r.logger.Error("Queue reader unable to retrieve tasks", tag.Error(err))
457 if common.IsResourceExhausted(err) {
462 return
463 }
464 > r.retrier.Reset() reader.go
465 >
466 > if len(tasks) != 0 {
467 for _, task := range tasks {
468 r.submit(task)
471 }
472
473 > if loadSlice.MoreTasks() { reader.go
474 r.notify()
475 return
476 }
477
478 > if r.nextReadSlice = r.nextReadSlice.Next(); r.nextReadSlice != nil { reader.go
479 r.notify()
480 return
482
483 // No more tasks to load, trigger completion callback.
484 > r.completionFn(r.readerID) reader.go
485 }
486
487 > func (r *ReaderImpl) resetNextReadSliceLocked() { reader.go
488 > r.nextReadSlice = nil
489 > for element := r.slices.Front(); element != nil; element = element.Next() {
490 > if element.Value.(Slice).MoreTasks() {
491 > r.nextReadSlice = element reader.go
492 > break
493 }
494 }
495
496 > if r.nextReadSlice != nil { reader.go
497 > r.notify() reader.go
498 > return
499 > }
500
501 // No more tasks to load, trigger completion callback.
503 }
504
505 > func (r *ReaderImpl) notify() { reader.go
506 > select {
507 > case r.notifyCh <- struct{}{}:
508 > default: reader.go
509 }
510 }
528 }
529
530 > func (r *ReaderImpl) verifyPendingTaskSize() bool { reader.go
531 > return r.monitor.GetTotalPendingTaskCount() < r.options.MaxPendingTasksCount()
532 > }
533
534 func mergeOrAppendSlice(
561 func validateSlicesOrderedDisjoint(
562 slices []Slice,
563 > ) { reader.go
564 > if len(slices) <= 1 {
565 > return reader.go
566 > }
567
568 for idx, slice := range slices[:len(slices)-1] {
go.temporal.io/server/service/matching/config.go 125 covered LOC · 1 range

Open complete file

278 func NewConfig(
279 dc *dynamicconfig.Collection,
280 > ) *Config { config.go
281 > return &Config{
282 > PersistenceMaxQPS: dynamicconfig.MatchingPersistenceMaxQPS.Get(dc),
283 > PersistenceGlobalMaxQPS: dynamicconfig.MatchingPersistenceGlobalMaxQPS.Get(dc),
284 > PersistenceNamespaceMaxQPS: dynamicconfig.MatchingPersistenceNamespaceMaxQPS.Get(dc),
285 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.MatchingPersistenceGlobalNamespaceMaxQPS.Get(dc),
286 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.DefaultPerShardNamespaceRPSMax,
287 > PersistenceDynamicRateLimitingParams: dynamicconfig.MatchingPersistenceDynamicRateLimitingParams.Get(dc),
288 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
289 > SyncMatchWaitDuration: dynamicconfig.MatchingSyncMatchWaitDuration.Get(dc),
290 > HistoryMaxPageSize: dynamicconfig.MatchingHistoryMaxPageSize.Get(dc),
291 > EnableDeployments: dynamicconfig.EnableDeployments.Get(dc), // [cleanup-wv-pre-release]
292 > EnableDeploymentVersions: dynamicconfig.EnableDeploymentVersions.Get(dc),
293 > UseRevisionNumberForWorkerVersioning: dynamicconfig.UseRevisionNumberForWorkerVersioning.Get(dc),
294 > MaxTaskQueuesInDeployment: dynamicconfig.MatchingMaxTaskQueuesInDeployment.Get(dc),
295 > MaxVersionsInTaskQueue: dynamicconfig.MatchingMaxVersionsInTaskQueue.Get(dc),
296 > RPS: dynamicconfig.MatchingRPS.Get(dc),
297 > NamespaceRPS: dynamicconfig.MatchingNamespaceRPS.Get(dc),
298 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
299 > PollWaitForNamespaceRateLimitToken: dynamicconfig.PollWaitForNamespaceRateLimitToken.Get(dc),
300 > RangeSize: 100000,
301 > NewMatcherSub: dynamicconfig.MatchingUseNewMatcher.Subscribe(dc),
302 > EnableFairnessSub: dynamicconfig.MatchingEnableFairness.Subscribe(dc),
303 > EnableMigration: dynamicconfig.MatchingEnableMigration.Get(dc),
304 > AutoEnableV2Sub: dynamicconfig.MatchingAutoEnableV2.Subscribe(dc),
305 > GetTasksBatchSize: dynamicconfig.MatchingGetTasksBatchSize.Get(dc),
306 > GetTasksReloadAt: dynamicconfig.MatchingGetTasksReloadAt.Get(dc),
307 > ForceReadTasksOnWrite: dynamicconfig.MatchingForceReadTasksOnWrite.Get(dc),
308 > UpdateAckInterval: dynamicconfig.MatchingUpdateAckInterval.Get(dc),
309 > MetadataUpdateOnAppendInterval: dynamicconfig.MatchingMetadataUpdateOnAppendInterval.Get(dc),
310 > MaxTaskQueueIdleTime: dynamicconfig.MatchingMaxTaskQueueIdleTime.Get(dc),
311 > LongPollExpirationInterval: dynamicconfig.MatchingLongPollExpirationInterval.Get(dc),
312 > BacklogTaskForwardTimeout: dynamicconfig.MatchingBacklogTaskForwardTimeout.Get(dc),
313 > ForwardPollRetryMaxInterval: dynamicconfig.MatchingForwardPollRetryMaxInterval.Get(dc),
314 > MinTaskThrottlingBurstSize: dynamicconfig.MatchingMinTaskThrottlingBurstSize.Get(dc),
315 > MaxTaskDeleteBatchSize: dynamicconfig.MatchingMaxTaskDeleteBatchSize.Get(dc),
316 > TaskDeleteInterval: dynamicconfig.MatchingTaskDeleteInterval.Get(dc),
317 > OutstandingTaskAppendsThreshold: dynamicconfig.MatchingOutstandingTaskAppendsThreshold.Get(dc),
318 > MaxTaskBatchSize: dynamicconfig.MatchingMaxTaskBatchSize.Get(dc),
319 > ThrottledLogRPS: dynamicconfig.MatchingThrottledLogRPS.Get(dc),
320 > NumTaskqueueWritePartitions: dynamicconfig.MatchingNumTaskqueueWritePartitions.Get(dc),
321 > NumTaskqueueReadPartitions: dynamicconfig.MatchingNumTaskqueueReadPartitions.Get(dc),
322 > NumTaskqueueReadPartitionsSub: dynamicconfig.MatchingNumTaskqueueReadPartitions.Subscribe(dc),
323 > BreakdownMetricsByTaskQueue: dynamicconfig.MetricsBreakdownByTaskQueue.Get(dc),
324 > BreakdownMetricsByPartition: dynamicconfig.MetricsBreakdownByPartition.Get(dc),
325 > BreakdownMetricsByBuildID: dynamicconfig.MetricsBreakdownByBuildID.Get(dc),
326 > EnableWorkerPluginMetrics: dynamicconfig.MatchingEnableWorkerPluginMetrics.Get(dc),
327 > EnablePollerAutoscalingMetrics: dynamicconfig.MatchingEnablePollerAutoscalingMetrics.Get(dc),
328 > ExternalPayloadsEnabled: dynamicconfig.ExternalPayloadsEnabled.Get(dc),
329 > WorkerRegistryNumBuckets: dynamicconfig.MatchingWorkerRegistryNumBuckets.Get(dc),
330 > WorkerRegistryEntryTTL: dynamicconfig.MatchingWorkerRegistryEntryTTL.Get(dc),
331 > WorkerRegistryMinEvictAge: dynamicconfig.MatchingWorkerRegistryMinEvictAge.Get(dc),
332 > WorkerRegistryMaxEntries: dynamicconfig.MatchingWorkerRegistryMaxEntries.Get(dc),
333 > WorkerRegistryEvictionInterval: dynamicconfig.MatchingWorkerRegistryEvictionInterval.Get(dc),
334 > ForwarderMaxOutstandingPolls: dynamicconfig.MatchingForwarderMaxOutstandingPolls.Get(dc),
335 > ForwarderMaxOutstandingTasks: dynamicconfig.MatchingForwarderMaxOutstandingTasks.Get(dc),
336 > ForwarderMaxRatePerSecond: dynamicconfig.MatchingForwarderMaxRatePerSecond.Get(dc),
337 > ForwarderMaxChildrenPerNode: dynamicconfig.MatchingForwarderMaxChildrenPerNode.Get(dc),
338 > AlignMembershipChange: dynamicconfig.MatchingAlignMembershipChange.Get(dc),
339 > ShutdownDrainDuration: dynamicconfig.MatchingShutdownDrainDuration.Get(dc),
340 > VersionCompatibleSetLimitPerQueue: dynamicconfig.VersionCompatibleSetLimitPerQueue.Get(dc),
341 > VersionBuildIdLimitPerQueue: dynamicconfig.VersionBuildIdLimitPerQueue.Get(dc),
342 > AssignmentRuleLimitPerQueue: dynamicconfig.AssignmentRuleLimitPerQueue.Get(dc),
343 > RedirectRuleLimitPerQueue: dynamicconfig.RedirectRuleLimitPerQueue.Get(dc),
344 > RedirectRuleMaxUpstreamBuildIDsPerQueue: dynamicconfig.RedirectRuleMaxUpstreamBuildIDsPerQueue.Get(dc),
345 > DeletedRuleRetentionTime: dynamicconfig.MatchingDeletedRuleRetentionTime.Get(dc),
346 > PollerHistoryTTL: dynamicconfig.PollerHistoryTTL.Get(dc),
347 > EnableMatchingFanOutForPollCancellation: dynamicconfig.EnableMatchingFanOutForPollCancellation.Get(dc),
348 > ReachabilityBuildIdVisibilityGracePeriod: dynamicconfig.ReachabilityBuildIdVisibilityGracePeriod.Get(dc),
349 > ReachabilityCacheOpenWFsTTL: dynamicconfig.ReachabilityCacheOpenWFsTTL.Get(dc),
350 > ReachabilityCacheClosedWFsTTL: dynamicconfig.ReachabilityCacheClosedWFsTTL.Get(dc),
351 > TaskQueueLimitPerBuildId: dynamicconfig.TaskQueuesPerBuildIdLimit.Get(dc),
352 > GetUserDataLongPollTimeout: dynamicconfig.MatchingGetUserDataLongPollTimeout.Get(dc), // Use -10 seconds so that we send back empty response instead of timeout
353 > GetUserDataRefresh: dynamicconfig.MatchingGetUserDataRefresh.Get(dc),
354 > EphemeralDataUpdateInterval: dynamicconfig.MatchingEphemeralDataUpdateInterval.Get(dc),
355 > BacklogMetricsEmitInterval: dynamicconfig.MatchingBacklogMetricsEmitInterval.Get(dc),
356 > PriorityBacklogForwarding: dynamicconfig.MatchingPriorityBacklogForwarding.Get(dc),
357 > BacklogNegligibleAge: dynamicconfig.MatchingBacklogNegligibleAge.Get(dc),
358 > MaxWaitForPollerBeforeFwd: dynamicconfig.MatchingMaxWaitForPollerBeforeFwd.Get(dc),
359 > QueryPollerUnavailableWindow: dynamicconfig.QueryPollerUnavailableWindow.Get(dc),
360 > WorkerControllerNoPollerHookWindow: dynamicconfig.WorkerControllerNoPollerHookWindow.Get(dc),
361 > EmitTaskDispatchLatencyAtPoll: dynamicconfig.MatchingEmitTaskDispatchLatencyAtPoll.Get(dc),
362 > QueryWorkflowTaskTimeoutLogRate: dynamicconfig.MatchingQueryWorkflowTaskTimeoutLogRate.Get(dc),
363 > MembershipUnloadDelay: dynamicconfig.MatchingMembershipUnloadDelay.Get(dc),
364 > TaskQueueInfoByBuildIdTTL: dynamicconfig.TaskQueueInfoByBuildIdTTL.Get(dc),
365 > PriorityLevels: dynamicconfig.MatchingPriorityLevels.Get(dc),
366 > RateLimiterRefreshInterval: time.Minute,
367 > FairnessKeyRateLimitCacheSize: dynamicconfig.MatchingFairnessKeyRateLimitCacheSize.Get(dc),
368 > MaxFairnessKeyWeightOverrides: dynamicconfig.MatchingMaxFairnessKeyWeightOverrides.Get(dc),
369 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
370 >
371 > AdminNamespaceToPartitionDispatchRate: dynamicconfig.AdminMatchingNamespaceToPartitionDispatchRate.Get(dc),
372 > AdminNamespaceToPartitionRateSub: dynamicconfig.AdminMatchingNamespaceToPartitionDispatchRate.Subscribe(dc),
373 > AdminNamespaceTaskqueueToPartitionDispatchRate: dynamicconfig.AdminMatchingNamespaceTaskqueueToPartitionDispatchRate.Get(dc),
374 > AdminNamespaceTaskqueueToPartitionRateSub: dynamicconfig.AdminMatchingNamespaceTaskqueueToPartitionDispatchRate.Subscribe(dc),
375 >
376 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
377 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
378 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
379 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
380 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
381 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
382 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
383 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
384 >
385 > ListNexusEndpointsLongPollTimeout: dynamicconfig.MatchingListNexusEndpointsLongPollTimeout.Get(dc),
386 > NexusEndpointsRefreshInterval: dynamicconfig.MatchingNexusEndpointsRefreshInterval.Get(dc),
387 > MinDispatchTaskTimeout: nexusoperations.MinDispatchTaskTimeout.Get(dc),
388 >
389 > PollerScalingBacklogAgeScaleUp: dynamicconfig.MatchingPollerScalingBacklogAgeScaleUp.Get(dc),
390 > PollerScalingWaitTime: dynamicconfig.MatchingPollerScalingWaitTime.Get(dc),
391 > PollerScalingDecisionsPerSecond: dynamicconfig.MatchingPollerScalingDecisionsPerSecond.Get(dc),
392 > PollerScalingTaskAddToDispatchRatio: dynamicconfig.MatchingPollerScalingTaskAddToDispatchRatio.Get(dc),
393 > EnablePollerScalingDecisionMetrics: dynamicconfig.MatchingEnablePollerScalingDecisionMetrics.Get(dc),
394 >
395 > FairnessCounter: dynamicconfig.MatchingFairnessCounter.Get(dc),
396 > FairnessPassDither: dynamicconfig.MatchingFairnessPassDither.Get(dc),
397 > PartitionScaleAllowedDrift: dynamicconfig.MatchingPartitionScaleAllowedDrift.Get(dc),
398 > PartitionScaleManagerSettings: dynamicconfig.MatchingPartitionScaleManager.Get(dc),
399 >
400 > LogAllReqErrors: dynamicconfig.LogAllReqErrors.Get(dc),
401 >
402 > RateLimitFractionProvider: defaultTaskQueueRateLimitFractionProvider,
403 > }
404 > }
405
406 func newTaskQueueConfig(tq *tqid.TaskQueue, config *Config, ns namespace.Name) *taskQueueConfig {
go.temporal.io/server/service/matching/matching_engine.go 124 covered LOC · 20 ranges

Open complete file

285 taskHookFactories []hooks.TaskHookFactory,
286 partitionScalerFactory PartitionScalerFactory,
287 > ) Engine { matching_engine.go
288 > scopedMetricsHandler := metricsHandler.WithTags(metrics.OperationTag(metrics.MatchingEngineScope))
289 > e := &matchingEngineImpl{
290 > status: common.DaemonStatusInitialized,
291 > taskManager: taskManager,
292 > fairTaskManager: fairTaskManager,
293 > historyClient: historyClient,
294 > matchingRawClient: matchingRawClient,
295 > tokenSerializer: tasktoken.NewSerializer(),
296 > workerDeploymentClient: workerDeploymentClient,
297 > historySerializer: historySerializer,
298 > logger: log.With(logger, tag.ComponentMatchingEngine),
299 > throttledLogger: log.With(throttledLogger, tag.ComponentMatchingEngine),
300 > namespaceRegistry: namespaceRegistry,
301 > hostInfoProvider: hostInfoProvider,
302 > serviceResolver: resolver,
303 > membershipChangedCh: make(chan *membership.ChangedEvent, 1), // allow one signal to be buffered while we're working
304 > clusterMeta: clusterMeta,
305 > timeSource: clock.NewRealTimeSource(), // No need to mock this at the moment
306 > visibilityManager: visibilityManager,
307 > nexusEndpointClient: newEndpointClient(config.NexusEndpointsRefreshInterval, nexusEndpointManager),
308 > // nexusEndpointsOwnershipLostCh initialized below
309 > saProvider: saProvider,
310 > saMapperProvider: saMapperProvider,
311 > metricsHandler: scopedMetricsHandler,
312 > partitions: make(map[tqid.PartitionKey]taskQueuePartitionManager),
313 > gaugeMetrics: gaugeMetrics{
314 > loadedTaskQueueFamilyCount: make(map[taskQueueCounterKey]int),
315 > loadedTaskQueueCount: make(map[taskQueueCounterKey]int),
316 > loadedTaskQueuePartitionCount: make(map[taskQueueCounterKey]int),
317 > loadedPhysicalTaskQueueCount: make(map[taskQueueCounterKey]int),
318 > },
319 > config: config,
320 > versionChecker: headers.NewDefaultVersionChecker(),
321 > testHooks: testHooks,
322 > queryResults: collection.NewSyncMap[string, chan *queryResult](),
323 > nexusResults: collection.NewSyncMap[string, chan *nexusResult](),
324 > outstandingPollers: collection.NewSyncMap[string, context.CancelFunc](),
325 > workerInstancePollers: workerPollerTracker{pollers: make(map[string]map[string]context.CancelFunc)},
326 > shutdownWorkers: cache.New(shutdownWorkersCacheMaxSize, &cache.Options{TTL: shutdownWorkersCacheTTL}),
327 > namespaceReplicationQueue: namespaceReplicationQueue,
328 > userDataUpdateBatchers: collection.NewSyncMap[namespace.ID, *stream_batcher.Batcher[*userDataUpdate, error]](),
329 > rateLimiter: rateLimiter,
330 > taskHookFactories: taskHookFactories,
331 > partitionScalerFactory: partitionScalerFactory,
332 > }
333 > e.nexusEndpointsOwnershipLostCh.Store(make(chan struct{}))
334 > e.reachabilityCache = newReachabilityCache(
335 > metrics.NoopMetricsHandler,
336 > visibilityManager,
337 > e.config.ReachabilityCacheOpenWFsTTL(),
338 > e.config.ReachabilityCacheClosedWFsTTL())
339 > return e
340 > }
341
342 > func (e *matchingEngineImpl) Start() { matching_engine.go
343 > if !atomic.CompareAndSwapInt32(
344 > &e.status,
345 > common.DaemonStatusInitialized,
346 > common.DaemonStatusStarted,
347 > ) {
348 return
349 }
350
351 > go e.watchMembership() matching_engine.go
352 > _ = e.serviceResolver.AddListener(e.listenerKey(), e.membershipChangedCh)
353 }
354
355 > func (e *matchingEngineImpl) Stop() { matching_engine.go
356 > if !atomic.CompareAndSwapInt32(
357 > &e.status,
358 > common.DaemonStatusStarted,
359 > common.DaemonStatusStopped,
360 > ) {
361 return
362 }
363
364 > _ = e.serviceResolver.RemoveListener(e.listenerKey()) matching_engine.go
365 > close(e.membershipChangedCh)
366 >
367 > e.nexusEndpointClient.notifyOwnershipChanged(false)
368 >
369 > for _, l := range e.getTaskQueuePartitions(math.MaxInt32) {
370 l.Stop(unloadCauseShuttingDown)
371 }
372 }
373
374 > func (e *matchingEngineImpl) listenerKey() string { matching_engine.go
375 > return fmt.Sprintf("matchingEngine[%p]", e)
376 > }
377
378 > func (e *matchingEngineImpl) watchMembership() { matching_engine.go
379 > self := e.hostInfoProvider.HostInfo().Identity()
380 > rc, ok := e.matchingRawClient.(matching.RoutingClient)
381 > if !ok {
382 e.logger.Warn("watchMembership found non-routing matching client")
383 return // this should only happen in unit tests
384 }
385 > ownedByOther := func(p tqid.Partition) bool { matching_engine.go
386 addr, err := rc.Route(p)
387 // don't take action on lookup error
389 }
390
391 > for range e.membershipChangedCh { matching_engine.go
392 > delay := e.config.MembershipUnloadDelay()
393 > if delay == 0 {
394 continue
395 }
396
397 > e.notifyNexusEndpointsOwnershipChange() matching_engine.go
398 >
399 > // Check all our loaded partitions to see if we lost ownership of any of them.
400 > e.partitionsLock.RLock()
401 > partitions := make([]tqid.Partition, 0, len(e.partitions))
402 > for _, pm := range e.partitions {
403 partitions = append(partitions, pm.Partition())
404 }
405 > e.partitionsLock.RUnlock() matching_engine.go
406 >
407 > partitions = util.FilterSlice(partitions, ownedByOther)
408 >
409 > const batchSize = 100
410 > for i := 0; i < len(partitions); i += batchSize {
411 // We don't own these anymore, but don't unload them immediately, wait a few seconds to ensure
412 // the membership update has propagated everywhere so that they won't get immediately re-loaded.
433 }
434
435 > func (e *matchingEngineImpl) getTaskQueuePartitions(maxCount int) (lists []taskQueuePartitionManager) { matching_engine.go
436 > e.partitionsLock.RLock()
437 > defer e.partitionsLock.RUnlock()
438 > lists = make([]taskQueuePartitionManager, 0, len(e.partitions))
439 > count := 0
440 > for _, tlMgr := range e.partitions {
441 lists = append(lists, tlMgr)
442 count++
2916 }
2917
2918 > func (e *matchingEngineImpl) checkNexusEndpointsOwnership() (bool, <-chan struct{}, error) { matching_engine.go
2919 > // Get the channel before checking the condition to prevent the channel from being closed while we're running this
2920 > // check.
2921 > ch := e.nexusEndpointsOwnershipLostCh.Load().(chan struct{}) //nolint:revive // type is always chan struct{}
2922 > self := e.hostInfoProvider.HostInfo().Identity()
2923 > owner, err := e.serviceResolver.Lookup(nexusEndpointsTablePartitionRoutingKey)
2924 > if err != nil {
2925 > return false, nil, fmt.Errorf("cannot resolve Nexus endpoints partition owner: %w", err) matching_engine.go
2926 > }
2927 > return owner.Identity() == self, ch, nil matching_engine.go
2928 }
2929
2930 > func (e *matchingEngineImpl) notifyNexusEndpointsOwnershipChange() { matching_engine.go
2931 > // We don't care about the channel returned here. This method is ensured to only be called from the single
2932 > // watchMembership method and is the only way the channel may be replaced.
2933 > isOwner, _, err := e.checkNexusEndpointsOwnership()
2934 > if err != nil {
2935 > e.logger.Error("Failed to check Nexus endpoints ownership", tag.Error(err)) matching_engine.go
2936 > return
2937 > }
2938 > if !isOwner { matching_engine.go
2939 close(e.nexusEndpointsOwnershipLostCh.Swap(make(chan struct{})).(chan struct{})) //nolint:revive // type is always chan struct{}
2940 }
2941 > e.nexusEndpointClient.notifyOwnershipChanged(isOwner) matching_engine.go
2942 }
2943
go.temporal.io/server/common/persistence/client/quotas.go 122 covered LOC · 18 ranges

Open complete file

70 metricsHandler metrics.Handler,
71 logger log.Logger,
72 > ) quotas.RequestRateLimiter { quotas.go
73 > hostRateFn := func() float64 { return float64(hostMaxQPS()) }
74
75 > return quotas.NewMultiRequestRateLimiter( quotas.go
76 > // host-level dynamic rate limiter
77 > newPriorityDynamicRateLimiter(
78 > hostRateFn,
79 > requestPriorityFn,
80 > operatorRPSRatio,
81 > burstRatio,
82 > healthSignals,
83 > dynamicParams,
84 > metricsHandler,
85 > logger,
86 > ),
87 > // basic host-level rate limiter
88 > newPriorityRateLimiter(
89 > hostRateFn,
90 > requestPriorityFn,
91 > operatorRPSRatio,
92 > burstRatio,
93 > ),
94 > )
95 }
96
101 operatorRPSRatio OperatorRPSRatio,
102 burstRatio PersistenceBurstRatio,
103 > ) quotas.RequestRateLimiter { quotas.go
104 >
105 > return newPriorityNamespaceRateLimiter(
106 > namespaceMaxQPS,
107 > hostMaxQPS,
108 > requestPriorityFn,
109 > operatorRPSRatio,
110 > burstRatio,
111 > )
112 > }
113
114 func NewPriorityNamespaceShardRateLimiter(
118 operatorRPSRatio OperatorRPSRatio,
119 burstRatio PersistenceBurstRatio,
120 > ) quotas.RequestRateLimiter { quotas.go
121 >
122 > return newPerShardPerNamespacePriorityRateLimiter(
123 > perShardNamespaceMaxQPS,
124 > hostMaxQPS,
125 > requestPriorityFn,
126 > operatorRPSRatio,
127 > burstRatio,
128 > )
129 > }
130
131 func newPerShardPerNamespacePriorityRateLimiter(
135 operatorRPSRatio OperatorRPSRatio,
136 burstRatio PersistenceBurstRatio,
137 > ) quotas.RequestRateLimiter { quotas.go
138 > return quotas.NewMapRequestRateLimiter(func(req quotas.Request) quotas.RequestRateLimiter {
139 > if hasCaller(req) && hasCallerSegment(req) {
140 return newPriorityRateLimiter(func() float64 {
141 if perShardNamespaceMaxQPS == nil || perShardNamespaceMaxQPS(req.Caller) <= 0 {
149 )
150 }
151 > return quotas.NoopRequestRateLimiter quotas.go
152 },
153 perShardPerNamespaceKeyFn,
155 }
156
157 > func perShardPerNamespaceKeyFn(req quotas.Request) perShardPerNamespaceKey { quotas.go
158 > return perShardPerNamespaceKey{
159 > namespaceID: req.Caller,
160 > shardID: req.CallerSegment,
161 > }
162 > }
163
164 func newPriorityNamespaceRateLimiter(
168 operatorRPSRatio OperatorRPSRatio,
169 burstRatio PersistenceBurstRatio,
170 > ) quotas.RequestRateLimiter { quotas.go
171 > return quotas.NewNamespaceRequestRateLimiter(func(req quotas.Request) quotas.RequestRateLimiter {
172 > if hasCaller(req) {
173 return newPriorityRateLimiter(
174 func() float64 {
189 )
190 }
191 > return quotas.NoopRequestRateLimiter quotas.go
192 })
193 }
198 operatorRPSRatio OperatorRPSRatio,
199 burstRatio PersistenceBurstRatio,
200 > ) quotas.RequestRateLimiter { quotas.go
201 > rateLimiters := make(map[int]quotas.RequestRateLimiter)
202 > for priority := range RequestPrioritiesOrdered {
203 > if priority == CallerTypeDefaultPriority[headers.CallerTypeOperator] {
204 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(
205 > quotas.NewDefaultRateLimiter(
206 > operatorRateFn(rateFn, operatorRPSRatio),
207 > quotas.BurstRatioFn(burstRatio),
208 > ),
209 > )
210 > } else {
211 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(
212 > quotas.NewDefaultRateLimiter(
213 > rateFn,
214 > quotas.BurstRatioFn(burstRatio),
215 > ),
216 > )
217 > }
218 }
219
220 > return quotas.NewPriorityRateLimiter( quotas.go
221 > requestPriorityFn,
222 > rateLimiters,
223 > )
224 }
225
233 metricsHandler metrics.Handler,
234 logger log.Logger,
235 > ) quotas.RequestRateLimiter { quotas.go
236 > rateLimiters := make(map[int]quotas.RequestRateLimiter)
237 > for priority := range RequestPrioritiesOrdered {
238 > // TODO: refactor this so dynamic rate adjustment is global for all priorities
239 > if priority == CallerTypeDefaultPriority[headers.CallerTypeOperator] {
240 > rateLimiters[priority] = NewHealthRequestRateLimiterImpl(
241 > healthSignals,
242 > operatorRateFn(rateFn, operatorRPSRatio),
243 > dynamicParams,
244 > burstRatio,
245 > metricsHandler,
246 > logger,
247 > )
248 > } else {
249 > rateLimiters[priority] = NewHealthRequestRateLimiterImpl(
250 > healthSignals,
251 > rateFn,
252 > dynamicParams,
253 > burstRatio,
254 > metricsHandler,
255 > logger,
256 > )
257 > }
258 }
259
260 > return quotas.NewPriorityRateLimiter( quotas.go
261 > requestPriorityFn,
262 > rateLimiters,
263 > )
264 }
265
266 > func RequestPriorityFn(req quotas.Request) int { quotas.go
267 > switch req.CallerType {
268 case headers.CallerTypeOperator:
269 return CallerTypeDefaultPriority[req.CallerType]
273 }
274 return CallerTypeDefaultPriority[req.CallerType]
275 > case headers.CallerTypeBackgroundHigh, headers.CallerTypeBackgroundLow: quotas.go
276 > if priority, ok := BackgroundTypeAPIPriorityOverride[req.API]; ok {
277 > return priority
278 > }
279 > return CallerTypeDefaultPriority[req.CallerType]
280 case headers.CallerTypePreemptable:
281 return CallerTypeDefaultPriority[req.CallerType]
282 > default: quotas.go
283 > // default requests to API priority to be consistent with existing behavior
284 > return CallerTypeDefaultPriority[headers.CallerTypeAPI]
285 }
286 }
287
288 > func operatorRateFn(rateFn quotas.RateFn, operatorRPSRatio OperatorRPSRatio) quotas.RateFn { quotas.go
289 > return func() float64 {
290 > return operatorRPSRatio() * rateFn()
291 > }
292 }
293
294 > func hasCaller(req quotas.Request) bool { quotas.go
295 > return req.Caller != "" && req.Caller != headers.CallerNameSystem
296 > }
297
298 func hasCallerSegment(req quotas.Request) bool {
go.temporal.io/server/service/matching/fx.go 122 covered LOC · 17 ranges

Open complete file

56 )
57
58 > func ServerProvider(grpcServerOptions []grpc.ServerOption) *grpc.Server { fx.go
59 > return grpc.NewServer(grpcServerOptions...)
60 > }
61
62 func ConfigProvider(
64 persistenceConfig config.Persistence,
65 rateLimitFractionProvider TaskQueueRateLimitFractionProvider,
66 > ) *Config { fx.go
67 > cfg := NewConfig(dc)
68 > cfg.RateLimitFractionProvider = rateLimitFractionProvider
69 > return cfg
70 > }
71
72 func ServiceErrorInterceptorProvider(
73 dc *dynamicconfig.Collection,
74 > ) *interceptor.ServiceErrorInterceptor { fx.go
75 > return interceptor.NewServiceErrorInterceptor(
76 > dynamicconfig.MaxServiceErrorMessageLength.Get(dc),
77 > )
78 > }
79
80 > func RetryableInterceptorProvider() *interceptor.RetryableInterceptor { fx.go
81 > return interceptor.NewRetryableInterceptor(
82 > common.CreateMatchingHandlerRetryPolicy(),
83 > common.IsServiceHandlerRetryableError,
84 > )
85 > }
86
87 func ErrorHandlerProvider(
88 logger log.Logger,
89 serviceConfig *Config,
90 > ) *interceptor.RequestErrorHandler { fx.go
91 > return interceptor.NewRequestErrorHandler(
92 > logger,
93 > serviceConfig.LogAllReqErrors,
94 > )
95 > }
96
97 func TelemetryInterceptorProvider(
101 serviceConfig *Config,
102 requestErrorHandler *interceptor.RequestErrorHandler,
103 > ) *interceptor.TelemetryInterceptor { fx.go
104 > return interceptor.NewTelemetryInterceptor(
105 > namespaceRegistry,
106 > metricsHandler,
107 > logger,
108 > serviceConfig.LogAllReqErrors,
109 > requestErrorHandler,
110 > )
111 > }
112
113 > func ThrottledLoggerRpsFnProvider(serviceConfig *Config) resource.ThrottledLoggerRpsFn { fx.go
114 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
115 }
116
119 namespaceRegistry namespace.Registry,
120 metricsHandler metrics.Handler,
121 > ) interceptor.NamespaceRateLimitInterceptor { fx.go
122 >
123 > namespaceRateFn := func(namespaceName string) float64 {
124 if namespaceRPS := serviceConfig.NamespaceRPS(namespaceName); namespaceRPS > 0 {
125 return float64(namespaceRPS)
129 }
130
131 > return interceptor.NewNamespaceRateLimitInterceptor( fx.go
132 > namespaceRegistry,
133 > configs.NewNamespaceRateLimiter(
134 > namespaceRateFn,
135 > serviceConfig.OperatorRPSRatio,
136 > ),
137 > map[string]int{}, // no token overrides
138 > configs.PollTaskAPISet, // set of APIs that will wait for token instead of immediate rejection
139 > serviceConfig.PollWaitForNamespaceRateLimitToken,
140 > metricsHandler,
141 > )
142 }
143
144 func RateLimitInterceptorProvider(
145 serviceConfig *Config,
146 > ) *interceptor.RateLimitInterceptor { fx.go
147 > return interceptor.NewRateLimitInterceptor(
148 > configs.NewPriorityRateLimiter(func() float64 { return float64(serviceConfig.RPS()) }, serviceConfig.OperatorRPSRatio),
149 map[string]int{
150 healthpb.Health_Check_FullMethodName: 0, // exclude health check requests from rate limiting.
159 persistenceLazyLoadedServiceResolver service.PersistenceLazyLoadedServiceResolver,
160 logger log.SnTaggedLogger,
161 > ) service.PersistenceRateLimitingParams { fx.go
162 > return service.NewPersistenceRateLimitingParams(
163 > serviceConfig.PersistenceMaxQPS,
164 > serviceConfig.PersistenceGlobalMaxQPS,
165 > serviceConfig.PersistenceNamespaceMaxQPS,
166 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
167 > serviceConfig.PersistencePerShardNamespaceMaxQPS,
168 > serviceConfig.OperatorRPSRatio,
169 > serviceConfig.PersistenceQPSBurstRatio,
170 > serviceConfig.PersistenceDynamicRateLimitingParams,
171 > persistenceLazyLoadedServiceResolver,
172 > logger,
173 > )
174 > }
175
176 func ServiceResolverProvider(
177 membershipMonitor membership.Monitor,
178 > ) (membership.ServiceResolver, error) { fx.go
179 > return membershipMonitor.GetResolver(primitives.MatchingService)
180 > }
181
182 // TaskQueueReplicatorNamespaceReplicationQueue is used to ensure the replicator only gets set if global namespaces are
207 chasmRegistry *chasm.Registry,
208 serializer serialization.Serializer,
209 > ) (manager.VisibilityManager, error) { fx.go
210 > return visibility.NewManager(
211 > *persistenceConfig,
212 > persistenceServiceResolver,
213 > customVisibilityStoreFactory,
214 > nil, // matching visibility never writes
215 > saProvider,
216 > searchAttributesMapperProvider,
217 > namespaceRegistry,
218 > chasmRegistry,
219 > serviceConfig.VisibilityPersistenceMaxReadQPS,
220 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
221 > serviceConfig.OperatorRPSRatio,
222 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
223 > serviceConfig.EnableReadFromSecondaryVisibility,
224 > serviceConfig.VisibilityEnableShadowReadMode,
225 > dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff), // matching visibility never writes
226 > serviceConfig.VisibilityDisableOrderByClause,
227 > serviceConfig.VisibilityEnableManualPagination,
228 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
229 > metricsHandler,
230 > logger,
231 > serializer,
232 > )
233 > }
234
235 > func ContextMetadataInterceptorProvider(logger log.Logger) *interceptor.ContextMetadataInterceptor { fx.go
236 > return interceptor.NewContextMetadataInterceptor(true, logger)
237 > }
238
239 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
240 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
241 > }
242
243 func WorkersRegistryProvider(
245 metricsHandler metrics.Handler,
246 serviceConfig *Config,
247 > ) workers.Registry { fx.go
248 > return workers.NewRegistry(lc, workers.RegistryParams{
249 > NumBuckets: serviceConfig.WorkerRegistryNumBuckets,
250 > TTL: serviceConfig.WorkerRegistryEntryTTL,
251 > MinEvictAge: serviceConfig.WorkerRegistryMinEvictAge,
252 > MaxItems: serviceConfig.WorkerRegistryMaxEntries,
253 > EvictionInterval: serviceConfig.WorkerRegistryEvictionInterval,
254 > MetricsHandler: metricsHandler,
255 > MetricsConfig: workers.WorkerMetricsConfig{
256 > EnablePluginMetrics: serviceConfig.EnableWorkerPluginMetrics,
257 > EnablePollerAutoscalingMetrics: serviceConfig.EnablePollerAutoscalingMetrics,
258 > BreakdownMetricsByTaskQueue: serviceConfig.BreakdownMetricsByTaskQueue,
259 > ExternalPayloadsEnabled: serviceConfig.ExternalPayloadsEnabled,
260 > },
261 > })
262 > }
263
264 > func simplePartitionScalerFactoryProvider(dc *dynamicconfig.Collection) PartitionScalerFactory { fx.go
265 > return newSimplePartitionScalerFactory(
266 > dynamicconfig.MatchingPartitionScaler.Get(dc),
267 > )
268 > }
go.temporal.io/server/common/rpc/rpc.go 120 covered LOC · 29 ranges

Open complete file

79 monitor membership.Monitor,
80 tokenProvider auth.TokenProvider,
81 > ) *RPCFactory { rpc.go
82 > authHeaderName := "authorization"
83 > requireRemoteClusterAuth := false
84 > if cfg != nil {
85 > authHeaderName = cmp.Or(cfg.Global.Authorization.AuthHeaderName, authHeaderName) rpc.go
86 > requireRemoteClusterAuth = cfg.Global.Authorization.RemoteClusterAuth.Require
87 > }
88 > f := &RPCFactory{ rpc.go
89 > config: cfg,
90 > serviceName: sName,
91 > logger: logger,
92 > metricsHandler: metricsHandler,
93 > frontendURL: frontendURL,
94 > frontendHTTPURL: frontendHTTPURL,
95 > frontendHTTPPort: frontendHTTPPort,
96 > frontendTLSConfig: frontendTLSConfig,
97 > tlsFactory: tlsProvider,
98 > commonDialOptions: commonDialOptions,
99 > perServiceDialOptions: perServiceDialOptions,
100 > tokenProvider: tokenProvider,
101 > authHeaderName: authHeaderName,
102 > requireRemoteClusterAuth: requireRemoteClusterAuth,
103 > monitor: monitor,
104 > }
105 > f.grpcListener = sync.OnceValue(f.createGRPCListener)
106 > f.localFrontendClient = sync.OnceValues(f.createLocalFrontendHTTPClient)
107 > return f
108 }
109
110 > func (d *RPCFactory) GetFrontendGRPCServerOptions() ([]grpc.ServerOption, error) { rpc.go
111 > var opts []grpc.ServerOption
112 >
113 > if d.tlsFactory != nil {
114 > serverConfig, err := d.tlsFactory.GetFrontendServerConfig() rpc.go
115 > if err != nil {
116 return nil, err
117 }
118 > if serverConfig == nil { rpc.go
119 > return opts, nil
120 > }
121 opts = append(opts, grpc.Creds(credentials.NewTLS(serverConfig)))
122 }
141 }
142
143 > func (d *RPCFactory) GetInternodeGRPCServerOptions() ([]grpc.ServerOption, error) { rpc.go
144 > var opts []grpc.ServerOption
145 >
146 > if d.EnableInternodeServerKeepalive {
147 rpcConfig := d.config.Services[string(d.serviceName)].RPC
148 kep := rpcConfig.KeepAliveServerConfig.GetKeepAliveEnforcementPolicy()
150 opts = append(opts, grpc.KeepaliveEnforcementPolicy(kep), grpc.KeepaliveParams(kp))
151 }
152 > if d.tlsFactory != nil { rpc.go
153 > serverConfig, err := d.tlsFactory.GetInternodeServerConfig() rpc.go
154 > if err != nil {
155 return nil, err
156 }
157 > if serverConfig == nil { rpc.go
158 > return opts, nil
159 > }
160 opts = append(opts, grpc.Creds(credentials.NewTLS(serverConfig)))
161 }
173
174 // GetGRPCListener returns cached dispatcher for gRPC inbound or creates one
175 > func (d *RPCFactory) GetGRPCListener() net.Listener { rpc.go
176 > return d.grpcListener()
177 > }
178
179 > func (d *RPCFactory) createGRPCListener() net.Listener { rpc.go
180 > rpcConfig := d.config.Services[string(d.serviceName)].RPC
181 > hostAddress := net.JoinHostPort(getListenIP(&rpcConfig, d.logger).String(), convert.IntToString(rpcConfig.GRPCPort))
182 >
183 > grpcListener, err := net.Listen("tcp", hostAddress)
184 > if err != nil || grpcListener == nil || grpcListener.Addr() == nil {
185 d.logger.Fatal("Failed to start gRPC listener", tag.Error(err), tag.Service(d.serviceName), tag.Address(hostAddress))
186 }
187
188 > d.logger.Info("Created gRPC listener", tag.Service(d.serviceName), tag.Address(hostAddress)) rpc.go
189 > return grpcListener
190 }
191
192 > func getListenIP(cfg *config.RPC, logger log.Logger) net.IP { rpc.go
193 > if cfg.BindOnLocalHost && len(cfg.BindOnIP) > 0 {
194 logger.Fatal("ListenIP failed, bindOnLocalHost and bindOnIP are mutually exclusive")
195 return nil
196 }
197
198 > if cfg.BindOnLocalHost { rpc.go
199 > return net.ParseIP(environment.GetLocalhostIP()) rpc.go
200 > }
201
202 > if len(cfg.BindOnIP) > 0 { rpc.go
203 > ip := net.ParseIP(cfg.BindOnIP)
204 > if ip != nil {
205 > return ip
206 > }
207 logger.Fatal("ListenIP failed, unable to parse bindOnIP value", tag.Address(cfg.BindOnIP))
208 return nil
261
262 // CreateLocalFrontendGRPCConnection creates connection for internal frontend calls
263 > func (d *RPCFactory) CreateLocalFrontendGRPCConnection() *grpc.ClientConn { rpc.go
264 > additionalDialOptions := append([]grpc.DialOption{}, d.perServiceDialOptions[primitives.InternalFrontendService]...)
265 >
266 > return d.dial(d.frontendURL, d.frontendTLSConfig, additionalDialOptions...)
267 > }
268
269 // createInternodeGRPCConnection creates connection for gRPC calls
290 }
291
292 > func (d *RPCFactory) dial(hostName string, tlsClientConfig *tls.Config, dialOptions ...grpc.DialOption) *grpc.ClientConn { rpc.go
293 > dialOptions = append(d.commonDialOptions, dialOptions...)
294 > connection, err := Dial(hostName, tlsClientConfig, d.logger, d.metricsHandler, dialOptions...)
295 > if err != nil {
296 d.logger.Fatal("Failed to create gRPC connection", tag.Error(err))
297 return nil
298 }
299
300 > return connection rpc.go
301 }
302
320
321 // CreateLocalFrontendHTTPClient gets or creates a cached frontend client.
322 > func (d *RPCFactory) CreateLocalFrontendHTTPClient() (*common.FrontendHTTPClient, error) { rpc.go
323 > return d.localFrontendClient()
324 > }
325
326 // createLocalFrontendHTTPClient creates an HTTP client for communicating with the frontend.
327 // It uses either the provided frontendURL or membership to resolve the frontend address.
328 > func (d *RPCFactory) createLocalFrontendHTTPClient() (*common.FrontendHTTPClient, error) { rpc.go
329 > // dialer and transport field values copied from http.DefaultTransport.
330 > dialer := &net.Dialer{
331 > Timeout: 30 * time.Second,
332 > KeepAlive: 30 * time.Second,
333 > }
334 > transport := &http.Transport{
335 > Proxy: http.ProxyFromEnvironment,
336 > DialContext: dialer.DialContext,
337 > ForceAttemptHTTP2: true,
338 > MaxIdleConns: 100,
339 > IdleConnTimeout: 90 * time.Second,
340 > TLSHandshakeTimeout: 10 * time.Second,
341 > ExpectContinueTimeout: 1 * time.Second,
342 > }
343 > client := http.Client{}
344 >
345 > // Default to http unless TLS is configured.
346 > scheme := "http"
347 > if d.frontendTLSConfig != nil {
348 transport.TLSClientConfig = d.frontendTLSConfig
349 scheme = "https"
350 }
351
352 > var address string rpc.go
353 > if r := serviceResolverFromGRPCURL(d.frontendHTTPURL); r != nil {
354 > client.Transport = &roundTripper{ rpc.go
355 > resolver: r,
356 > underlying: transport,
357 > httpPort: d.frontendHTTPPort,
358 > }
359 > address = "internal" // This will be replaced by the roundTripper
360 > } else { rpc.go
361 // Use the URL as-is and leave the transport unmodified.
362 client.Transport = transport
364 }
365
366 > return &common.FrontendHTTPClient{ rpc.go
367 > Client: client,
368 > Address: address,
369 > Scheme: scheme,
370 > }, nil
371 }
372
401 // serviceResolverFromGRPCURL returns a ServiceResolver if ustr corresponds to a
402 // membership url, otherwise nil.
403 > func serviceResolverFromGRPCURL(ustr string) membership.ServiceResolver { rpc.go
404 > u, err := url.Parse(ustr)
405 > if err != nil {
406 return nil
407 }
408 > res, err := membership.GetServiceResolverFromURL(u) rpc.go
409 > if err != nil {
410 return nil
411 }
412 > return res rpc.go
413 }
go.temporal.io/server/common/backoff/retrypolicy.go 117 covered LOC · 30 ranges

Open complete file

80
81 // NewExponentialRetryPolicy returns an instance of ExponentialRetryPolicy using the provided initialInterval
82 > func NewExponentialRetryPolicy(initialInterval time.Duration) *ExponentialRetryPolicy { retrypolicy.go
83 > p := &ExponentialRetryPolicy{
84 > initialInterval: initialInterval,
85 > backoffCoefficient: defaultBackoffCoefficient,
86 > maximumInterval: defaultMaximumInterval,
87 > expirationInterval: defaultExpirationInterval,
88 > maximumAttempts: defaultMaximumAttempts,
89 > }
90 >
91 > return p
92 > }
93
94 // NewRetrier is used for creating a new instance of Retrier
95 > func NewRetrier(policy RetryPolicy, timeSource clock.TimeSource) Retrier { retrypolicy.go
96 > return &retrierImpl{
97 > policy: policy,
98 > timeSource: timeSource,
99 > startTime: timeSource.Now(),
100 > currentAttempt: 1,
101 > }
102 > }
103
104 // WithInitialInterval sets the initial interval used by ExponentialRetryPolicy for the very first retry
113 // All retries are computed using the following formula:
114 // initialInterval * math.Pow(backoffCoefficient, currentAttempt)
115 > func (p *ExponentialRetryPolicy) WithBackoffCoefficient(backoffCoefficient float64) *ExponentialRetryPolicy { retrypolicy.go
116 > p.backoffCoefficient = backoffCoefficient
117 > return p
118 > }
119
120 // WithMaximumInterval sets the maximum interval for each retry.
121 // This does *not* cause the policy to stop retrying when the interval between retries reaches the supplied duration.
122 // That is what WithExpirationInterval does. Instead, this prevents the interval from exceeding maximumInterval.
123 > func (p *ExponentialRetryPolicy) WithMaximumInterval(maximumInterval time.Duration) *ExponentialRetryPolicy { retrypolicy.go
124 > p.maximumInterval = maximumInterval
125 > return p
126 > }
127
128 // WithExpirationInterval sets the absolute expiration interval for all retries
129 > func (p *ExponentialRetryPolicy) WithExpirationInterval(expirationInterval time.Duration) *ExponentialRetryPolicy { retrypolicy.go
130 > p.expirationInterval = expirationInterval
131 > return p
132 > }
133
134 // WithMaximumAttempts sets the maximum number of retry attempts
135 > func (p *ExponentialRetryPolicy) WithMaximumAttempts(maximumAttempts int) *ExponentialRetryPolicy { retrypolicy.go
136 > p.maximumAttempts = maximumAttempts
137 > return p
138 > }
139
140 // ComputeNextDelay returns the next delay interval. This is used by Retrier to delay calling the operation again
141 > func (p *ExponentialRetryPolicy) ComputeNextDelay(elapsedTime time.Duration, numAttempts int, _ error) time.Duration { retrypolicy.go
142 > // Check to see if we ran out of maximum number of attempts
143 > // NOTE: if maxAttempts is X, return done when numAttempts == X, otherwise there will be attempt X+1
144 > if p.maximumAttempts != noMaximumAttempts && numAttempts >= p.maximumAttempts {
145 return done
146 }
147
148 // Stop retrying after expiration interval is elapsed
149 > if p.expirationInterval != NoInterval && elapsedTime > p.expirationInterval { retrypolicy.go
150 return done
151 }
152
153 > nextInterval := float64(p.initialInterval) * math.Pow(p.backoffCoefficient, float64(numAttempts-1)) retrypolicy.go
154 > // Disallow retries if initialInterval is negative or nextInterval overflows
155 > if nextInterval <= 0 {
156 return done
157 }
158 > if p.maximumInterval != NoInterval { retrypolicy.go
159 > nextInterval = math.Min(nextInterval, float64(p.maximumInterval)) retrypolicy.go
160 > }
161
162 > if p.expirationInterval != NoInterval { retrypolicy.go
163 > remainingTime := float64(math.Max(0, float64(p.expirationInterval-elapsedTime))) retrypolicy.go
164 > nextInterval = math.Min(remainingTime, nextInterval)
165 > }
166
167 // Bail out if the next interval is smaller than initial retry interval
168 > nextDuration := time.Duration(nextInterval) retrypolicy.go
169 > if nextDuration < p.initialInterval {
170 return done
171 }
172
173 > nextInterval = p.addJitter(nextInterval) retrypolicy.go
174 >
175 > return time.Duration(nextInterval)
176 }
177
178 > func (p *ExponentialRetryPolicy) addJitter(nextInterval float64) float64 { retrypolicy.go
179 > // add jitter to avoid global synchronization
180 > jitterPortion := max(
181 > // Prevent overflow
182 > int(0.2*nextInterval), 1)
183 > nextInterval = nextInterval*0.8 + float64(getJitterRand().Intn(jitterPortion))
184 > return nextInterval
185 > }
186
187 func (r *disabledRetryPolicyImpl) ComputeNextDelay(_ time.Duration, _ int, _ error) time.Duration {
203 // NewConditionalRetryPolicy returns a policy that delegates to whenTrue when
204 // predicate(err) is true, and whenFalse otherwise.
205 > func NewConditionalRetryPolicy(predicate func(err error) bool, whenTrue, whenFalse RetryPolicy) *ConditionalRetryPolicy { retrypolicy.go
206 > return &ConditionalRetryPolicy{
207 > predicate: predicate,
208 > whenTrue: whenTrue,
209 > whenFalse: whenFalse,
210 > }
211 > }
212
213 > func (p *ConditionalRetryPolicy) ComputeNextDelay(elapsedTime time.Duration, numAttempts int, err error) time.Duration { retrypolicy.go
214 > if p.predicate(err) {
215 return p.whenTrue.ComputeNextDelay(elapsedTime, numAttempts, err)
216 }
217 > return p.whenFalse.ComputeNextDelay(elapsedTime, numAttempts, err) retrypolicy.go
218 }
219
220 // Reset will set the Retrier into initial state
221 > func (r *retrierImpl) Reset() { retrypolicy.go
222 > r.startTime = r.timeSource.Now()
223 > r.currentAttempt = 1
224 > }
225
226 // NextBackOff returns the next delay interval. This is used by Retry to delay calling the operation again
227 > func (r *retrierImpl) NextBackOff(err error) time.Duration { retrypolicy.go
228 > nextInterval := r.policy.ComputeNextDelay(r.getElapsedTime(), r.currentAttempt, err)
229 >
230 > // Now increment the current attempt
231 > r.currentAttempt++
232 > return nextInterval
233 > }
234
235 > func (r *retrierImpl) getElapsedTime() time.Duration { retrypolicy.go
236 > return r.timeSource.Now().Sub(r.startTime)
237 > }
238
239 var _ RetryPolicy = (*ErrorDependentRetryPolicy)(nil)
267 var _ RetryPolicy = (*ConstantDelayRetryPolicy)(nil)
268
269 > func NewConstantDelayRetryPolicy(delay time.Duration) *ConstantDelayRetryPolicy { retrypolicy.go
270 > return &ConstantDelayRetryPolicy{
271 > maximumAttempts: defaultMaximumAttempts,
272 > jitterPct: defaultJitterPct,
273 > delay: delay,
274 > }
275 > }
276
277 > func (p *ConstantDelayRetryPolicy) WithMaximumAttempts(maximumAttempts int) *ConstantDelayRetryPolicy { retrypolicy.go
278 > p.maximumAttempts = maximumAttempts
279 > return p
280 > }
281
282 func (p *ConstantDelayRetryPolicy) WithJitter(jitterPct float64) *ConstantDelayRetryPolicy {
297 }
298
299 > func getJitterRand() *rand.Rand { retrypolicy.go
300 > if r := jitterRand.Load(); r != nil {
301 > return r retrypolicy.go
302 > }
303 > r := rand.New(NewRetryLockedSource()) retrypolicy.go
304 >
305 > if !jitterRand.CompareAndSwap(nil, r) {
306 // Two different goroutines called some top-level
307 // function at the same time. While the results in
330 }
331
332 > func (r *RetryLockedSource) Int63() int64 { retrypolicy.go
333 > r.lk.Lock()
334 > defer r.lk.Unlock()
335 > return r.s.Int63()
336 > }
337
338 func (r *RetryLockedSource) Seed(seed int64) {
340 }
341
342 > func NewRetryLockedSource() *RetryLockedSource { retrypolicy.go
343 > return &RetryLockedSource{
344 > lk: sync.Mutex{},
345 > s: rand.NewSource(time.Now().UnixNano()),
346 > }
347 > }
go.temporal.io/server/common/nexus/endpoint_registry.go 117 covered LOC · 22 ranges

Open complete file

74 var ErrNexusDisabled = serviceerror.NewFailedPrecondition("nexus is disabled")
75
76 > func NewEndpointRegistryConfig(dc *dynamicconfig.Collection) *EndpointRegistryConfig { endpoint_registry.go
77 > config := &EndpointRegistryConfig{
78 > refreshLongPollTimeout: dynamicconfig.RefreshNexusEndpointsLongPollTimeout.Get(dc),
79 > refreshPageSize: dynamicconfig.NexusEndpointListDefaultPageSize.Get(dc),
80 > refreshMinWait: dynamicconfig.RefreshNexusEndpointsMinWait.Get(dc),
81 > readThroughCacheSize: dynamicconfig.NexusReadThroughCacheSize.Get(dc),
82 > readThroughCacheTTL: dynamicconfig.NexusReadThroughCacheTTL.Get(dc),
83 > refreshOnRead: dynamicconfig.ForceNexusEndpointRefreshOnRead.Get(dc),
84 > }
85 > config.refreshRetryPolicy = backoff.NewExponentialRetryPolicy(config.refreshMinWait()).WithMaximumInterval(config.refreshLongPollTimeout())
86 > return config
87 > }
88
89 func NewEndpointRegistry(
93 logger log.Logger,
94 metricsHandler metrics.Handler,
95 > ) *EndpointRegistryImpl { endpoint_registry.go
96 > return &EndpointRegistryImpl{
97 > config: config,
98 > endpointsByID: make(map[string]*persistencespb.NexusEndpointEntry),
99 > endpointsByName: make(map[string]*persistencespb.NexusEndpointEntry),
100 > matchingClient: matchingClient,
101 > persistence: persistence,
102 > logger: logger,
103 > readThroughCacheByID: cache.NewWithMetrics(config.readThroughCacheSize(), &cache.Options{
104 > TTL: config.readThroughCacheTTL(),
105 > }, metricsHandler.WithTags(metrics.CacheTypeTag(metrics.NexusEndpointRegistryReadThroughCacheTypeTagValue))),
106 > }
107 > }
108
109 // StartLifecycle starts this component. It should only be invoked by an fx lifecycle hook.
110 // Should not be called multiple times or concurrently with StopLifecycle()
111 > func (r *EndpointRegistryImpl) StartLifecycle() { endpoint_registry.go
112 > r.setEnabled(true)
113 > }
114
115 // StopLifecycle stops this component. It should only be invoked by an fx lifecycle hook.
116 // Should not be called multiple times or concurrently with StartLifecycle()
117 > func (r *EndpointRegistryImpl) StopLifecycle() { endpoint_registry.go
118 > r.setEnabled(false)
119 > }
120
121 > func (r *EndpointRegistryImpl) setEnabled(enabled bool) { endpoint_registry.go
122 > oldReady := r.dataReady.Load()
123 > if oldReady == nil && enabled {
124 > backgroundCtx := headers.SetCallerInfo(
125 > context.Background(),
126 > headers.SystemBackgroundHighCallerInfo,
127 > )
128 > newReady := &dataReady{
129 > refresh: goro.NewHandle(backgroundCtx),
130 > ready: make(chan struct{}),
131 > }
132 > if r.dataReady.CompareAndSwap(oldReady, newReady) {
133 > newReady.refresh.Go(func(ctx context.Context) error {
134 > return r.refreshEndpointsLoop(ctx, newReady)
135 > })
136 }
137 > } else if oldReady != nil && !enabled { endpoint_registry.go
138 > if r.dataReady.CompareAndSwap(oldReady, nil) {
139 > oldReady.refresh.Cancel()
140 > <-oldReady.refresh.Done()
141 > // If oldReady.ready was not already closed here, callers blocked in waitUntilInitialized
142 > // will block indefinitely (until context timeout). If we wanted to wake them up, we
143 > // could close ready here, but we would need to use a sync.Once to avoid closing it
144 > // twice. Then waitUntilInitialized would need to reload r.dataReady to check that the
145 > // wakeup was due to data being ready rather than this close.
146 > }
147 }
148 }
222 }
223
224 > func (r *EndpointRegistryImpl) refreshEndpointsLoop(ctx context.Context, dataReady *dataReady) error { endpoint_registry.go
225 > hasLoadedEndpointData := false
226 >
227 > for ctx.Err() == nil {
228 > start := time.Now()
229 > enforceMinWait := true
230 > if !hasLoadedEndpointData {
231 > // Loading endpoints for the first time after being (re)enabled, so load with fallback to persistence
232 > // and unblock any threads waiting on r.dataReady if successful.
233 > err := backoff.ThrottleRetryContext(ctx, r.loadEndpoints, r.config.refreshRetryPolicy, nil)
234 > if err == nil {
235 hasLoadedEndpointData = true
236 enforceMinWait = false
253 r.dataLock.Unlock()
254 }
255 > elapsed := time.Since(start) endpoint_registry.go
256 >
257 > minWaitTime := r.config.refreshMinWait()
258 > // In general, we want to start a new call immediately on completion of the previous one. But if the remote is
259 > // broken and returns success immediately, we might end up spinning. So enforce a minimum wait time that
260 > // increases as long as we keep getting very fast replies. Only enforce the min wait if the remote does not
261 > // return new data.
262 > if enforceMinWait && elapsed < minWaitTime {
263 > util.InterruptibleSleep(ctx, minWaitTime-elapsed) endpoint_registry.go
264 > }
265 }
266
267 > return ctx.Err() endpoint_registry.go
268 }
269
270 // loadEndpoints initializes the in-memory view of endpoints data.
271 // It first tries to load from matching service and falls back to querying persistence directly if matching is unavailable.
272 > func (r *EndpointRegistryImpl) loadEndpoints(ctx context.Context) error { endpoint_registry.go
273 > tableVersion, endpoints, err := r.getAllEndpointsMatchingWithPersistenceFallback(ctx)
274 > if err != nil {
275 > return err endpoint_registry.go
276 > }
277 endpointsByID := make(map[string]*persistencespb.NexusEndpointEntry, len(endpoints))
278 endpointsByName := make(map[string]*persistencespb.NexusEndpointEntry, len(endpoints))
366 }
367
368 > func (r *EndpointRegistryImpl) getAllEndpointsMatchingWithPersistenceFallback(ctx context.Context) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
369 > tableVersion, endpoints, err := r.getAllEndpointsMatching(ctx)
370 > if err != nil {
371 > // Fallback to persistence on matching error during initial load. endpoint_registry.go
372 > r.logger.Error("error from matching when initializing Nexus endpoint cache", tag.Error(err))
373 > tableVersion, endpoints, err = r.getAllEndpointsPersistence(ctx)
374 > }
375 > return tableVersion, endpoints, err endpoint_registry.go
376 }
377
378 // getAllEndpointsMatching paginates over all endpoints returned by matching. It always does a simple get.
379 > func (r *EndpointRegistryImpl) getAllEndpointsMatching(ctx context.Context) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
380 > return r.getAllEndpoints(ctx, func(currentTableVersion int64, currentPageToken []byte) (int64, []byte, []*persistencespb.NexusEndpointEntry, error) {
381 > resp, err := r.matchingClient.ListNexusEndpoints(ctx, &matchingservice.ListNexusEndpointsRequest{
382 > NextPageToken: currentPageToken,
383 > PageSize: int32(r.config.refreshPageSize()),
384 > LastKnownTableVersion: currentTableVersion,
385 > Wait: false,
386 > })
387 > if err != nil {
388 > return 0, nil, nil, err endpoint_registry.go
389 > }
390 return resp.TableVersion, resp.NextPageToken, resp.Entries, nil
391 })
394 // getAllEndpointsPersistence paginates over all endpoints returned by persistence.
395 // Should only be used as a fall-back if matching service is unavailable during initial load.
396 > func (r *EndpointRegistryImpl) getAllEndpointsPersistence(ctx context.Context) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
397 > return r.getAllEndpoints(ctx, func(currentTableVersion int64, currentPageToken []byte) (int64, []byte, []*persistencespb.NexusEndpointEntry, error) {
398 resp, err := r.persistence.ListNexusEndpoints(ctx, &p.ListNexusEndpointsRequest{
399 LastKnownTableVersion: currentTableVersion,
410 // getAllEndpointsPersistence paginates over all endpoints returned by persistence.
411 // Should only be used as a fall-back if matching service is unavailable during initial load.
412 > func (r *EndpointRegistryImpl) getAllEndpoints(ctx context.Context, getter func(int64, []byte) (int64, []byte, []*persistencespb.NexusEndpointEntry, error)) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
413 > var currentPageToken []byte
414 >
415 > currentTableVersion := int64(0)
416 > entries := make([]*persistencespb.NexusEndpointEntry, 0)
417 >
418 > for ctx.Err() == nil {
419 > respTableVersion, respNextPageToken, respEntries, err := getter(currentTableVersion, currentPageToken)
420 > if err != nil {
421 > var fpe *serviceerror.FailedPrecondition endpoint_registry.go
422 > if errors.As(err, &fpe) && fpe.Message == p.ErrNexusTableVersionConflict.Error() {
423 // indicates table was updated during paging, so reset and start from the beginning.
424 currentPageToken = nil
go.temporal.io/server/service/history/replication/stream_receiver_monitor.go 115 covered LOC · 29 ranges

Open complete file

56 executableTaskConverter ExecutableTaskConverter,
57 enableStreaming bool,
58 > ) *StreamReceiverMonitorImpl { stream_receiver_monitor.go
59 > return &StreamReceiverMonitorImpl{
60 > ProcessToolBox: processToolBox,
61 > executableTaskConverter: executableTaskConverter,
62 > enableStreaming: enableStreaming,
63 >
64 > status: streamStatusInitialized,
65 > shutdownOnce: channel.NewShutdownOnce(),
66 >
67 > inboundStreams: make(map[ClusterShardKeyPair]StreamSender),
68 > outboundStreams: make(map[ClusterShardKeyPair]StreamReceiver),
69 > }
70 > }
71
72 > func (m *StreamReceiverMonitorImpl) Start() { stream_receiver_monitor.go
73 > if !atomic.CompareAndSwapInt32(
74 > &m.status,
75 > common.DaemonStatusInitialized,
76 > common.DaemonStatusStarted,
77 > ) {
78 return
79 }
80 > if !m.enableStreaming { stream_receiver_monitor.go
81 return
82 }
83
84 > go m.eventLoop() stream_receiver_monitor.go
85 > go m.statusMonitorLoop()
86 >
87 > m.Logger.Info("StreamReceiverMonitor started.")
88 }
89
90 > func (m *StreamReceiverMonitorImpl) Stop() { stream_receiver_monitor.go
91 > if !atomic.CompareAndSwapInt32(
92 > &m.status,
93 > common.DaemonStatusStarted,
94 > common.DaemonStatusStopped,
95 > ) {
97 > }
98 > if !m.enableStreaming { stream_receiver_monitor.go
99 return
100 }
101
102 > m.shutdownOnce.Shutdown() stream_receiver_monitor.go
103 > m.Lock()
104 > defer m.Unlock()
105 > for serverKey, stream := range m.outboundStreams {
106 stream.Stop()
107 delete(m.outboundStreams, serverKey)
108 }
109 > if m.Config.EnableCloseInboundReplicationStreamOnShutdown() { stream_receiver_monitor.go
110 > for clientKey, stream := range m.inboundStreams { stream_receiver_monitor.go
111 stream.Stop()
112 delete(m.inboundStreams, clientKey)
113 }
114 }
115 > m.Logger.Info("StreamReceiverMonitor stopped.") stream_receiver_monitor.go
116 }
117
131 }
132
133 > func (m *StreamReceiverMonitorImpl) eventLoop() { stream_receiver_monitor.go
134 > defer m.Stop()
135 > ticker := time.NewTicker(streamReceiverMonitorInterval)
136 > defer ticker.Stop()
137 >
138 > clusterMetadataChangeChan := make(chan struct{}, 1)
139 > m.ClusterMetadata.RegisterMetadataChangeCallback(m, func(_ map[string]*cluster.ClusterInformation, _ map[string]*cluster.ClusterInformation) {
140 > select {
141 > case clusterMetadataChangeChan <- struct{}{}:
142 default:
143 }
144 })
145 > defer m.ClusterMetadata.UnRegisterMetadataChangeCallback(m) stream_receiver_monitor.go
146 > m.reconcileOutboundStreams()
147 >
148 > Loop:
149 > for !m.shutdownOnce.IsShutdown() {
150 > select {
151 > case <-clusterMetadataChangeChan:
152 > m.reconcileInboundStreams()
153 > m.reconcileOutboundStreams()
154 case <-ticker.C:
155 m.reconcileInboundStreams()
156 m.reconcileOutboundStreams()
157 > case <-m.shutdownOnce.Channel(): stream_receiver_monitor.go
158 > break Loop
159 }
160 }
161 }
162
163 > func (m *StreamReceiverMonitorImpl) reconcileInboundStreams() { stream_receiver_monitor.go
164 > streamKeys := m.generateInboundStreamKeys()
165 > m.doReconcileInboundStreams(streamKeys)
166 > }
167
168 > func (m *StreamReceiverMonitorImpl) reconcileOutboundStreams() { stream_receiver_monitor.go
169 > streamKeys := m.generateOutboundStreamKeys()
170 > m.doReconcileOutboundStreams(streamKeys)
171 > }
172
173 > func (m *StreamReceiverMonitorImpl) generateInboundStreamKeys() map[ClusterShardKeyPair]struct{} { stream_receiver_monitor.go
174 > allClusterInfo := m.ClusterMetadata.GetAllClusterInfo()
175 >
176 > clientClusterIDs := make(map[int32]struct{})
177 > serverClusterID := int32(m.ClusterMetadata.GetClusterID())
178 > clusterIDToShardCount := make(map[int32]int32)
179 > for _, clusterInfo := range allClusterInfo {
180 > clusterIDToShardCount[int32(clusterInfo.InitialFailoverVersion)] = clusterInfo.ShardCount
181 >
182 > if !cluster.IsReplicationEnabledForCluster(clusterInfo, m.Config.EnableSeparateReplicationEnableFlag()) || int32(clusterInfo.InitialFailoverVersion) == serverClusterID {
183 > continue
184 }
185 clientClusterIDs[int32(clusterInfo.InitialFailoverVersion)] = struct{}{}
186 }
187 > streamKeys := make(map[ClusterShardKeyPair]struct{}) stream_receiver_monitor.go
188 > for _, shardID := range m.ShardController.ShardIDs() {
189 for clientClusterID := range clientClusterIDs {
190 serverShardID := shardID
205 }
206 }
207 > return streamKeys stream_receiver_monitor.go
208 }
209
210 > func (m *StreamReceiverMonitorImpl) generateOutboundStreamKeys() map[ClusterShardKeyPair]struct{} { stream_receiver_monitor.go
211 > allClusterInfo := m.ClusterMetadata.GetAllClusterInfo()
212 >
213 > clientClusterID := int32(m.ClusterMetadata.GetClusterID())
214 > serverClusterIDs := make(map[int32]struct{})
215 > clusterIDToShardCount := make(map[int32]int32)
216 > for _, clusterInfo := range allClusterInfo {
217 > clusterIDToShardCount[int32(clusterInfo.InitialFailoverVersion)] = clusterInfo.ShardCount
218 >
219 > if !clusterInfo.Enabled || !cluster.IsReplicationEnabledForCluster(clusterInfo, m.Config.EnableSeparateReplicationEnableFlag()) || int32(clusterInfo.InitialFailoverVersion) == clientClusterID {
220 > continue
221 }
222 serverClusterIDs[int32(clusterInfo.InitialFailoverVersion)] = struct{}{}
223 }
224 > streamKeys := make(map[ClusterShardKeyPair]struct{}) stream_receiver_monitor.go
225 > for _, shardID := range m.ShardController.ShardIDs() {
226 for serverClusterID := range serverClusterIDs {
227 clientShardID := shardID
242 }
243 }
244 > return streamKeys stream_receiver_monitor.go
245 }
246
247 func (m *StreamReceiverMonitorImpl) doReconcileInboundStreams(
248 streamKeys map[ClusterShardKeyPair]struct{},
250 > m.Lock()
251 > defer m.Unlock()
252 > if m.shutdownOnce.IsShutdown() {
253 return
254 }
255
256 > for streamKey, stream := range m.inboundStreams { stream_receiver_monitor.go
257 if !stream.IsValid() {
258 stream.Stop()
267 func (m *StreamReceiverMonitorImpl) doReconcileOutboundStreams(
268 streamKeys map[ClusterShardKeyPair]struct{},
270 > m.Lock()
271 > defer m.Unlock()
272 > if m.shutdownOnce.IsShutdown() {
273 return
274 }
275
276 > for streamKey, stream := range m.outboundStreams { stream_receiver_monitor.go
277 if !stream.IsValid() {
278 stream.Stop()
283 }
284 }
285 > for streamKey := range streamKeys { stream_receiver_monitor.go
286 if _, ok := m.outboundStreams[streamKey]; !ok {
287 stream := NewStreamReceiver(
297 }
298
299 > func (m *StreamReceiverMonitorImpl) statusMonitorLoop() { stream_receiver_monitor.go
300 > ticker := time.NewTicker(5 * time.Minute)
301 > defer ticker.Stop()
302 >
303 > for {
304 > select {
305 case <-ticker.C:
306 m.monitorStreamStatus()
307 > case <-m.shutdownOnce.Channel(): stream_receiver_monitor.go
308 > return
309 }
310 }
go.temporal.io/server/common/dynamicconfig/collection.go 113 covered LOC · 23 ranges

Open complete file

111 // NewCollection creates a new collection. For subscriptions to work, you must call Start/Stop.
112 // Get will work without Start/Stop.
113 > func NewCollection(client Client, logger log.Logger) *Collection { collection.go
114 > // Do this at the first convenient place we have a logger:
115 > logSharedStructureWarnings(logger)
116 >
117 > return &Collection{
118 > client: client,
119 > logger: logger,
120 > errCount: -1,
121 > subscriptions: make(map[Key]map[int]any),
122 > convertCache: new(sync.Map),
123 > indexCache: new(sync.Map),
124 > }
125 > }
126
127 > func (c *Collection) Start() { collection.go
128 > c.subscriptionLock.Lock()
129 > defer c.subscriptionLock.Unlock()
130 > if notifyingClient, ok := c.client.(NotifyingClient); ok {
131 c.cancelClientSubscription = notifyingClient.Subscribe(c.keysChanged)
132 > } else { collection.go
133 > c.poller.Go(c.pollForChanges) collection.go
134 > }
135 }
136
137 > func (c *Collection) Stop() { collection.go
138 > c.poller.Cancel()
139 > c.poller.Wait()
140 > if c.cancelClientSubscription != nil {
141 c.cancelClientSubscription()
142 }
144
145 // Implement pingable.Pingable
146 > func (c *Collection) GetPingChecks() []pingable.Check { collection.go
147 > return []pingable.Check{
148 > {
149 > Name: "dynamic config callbacks",
150 > Timeout: 5 * time.Second,
151 > Ping: func() []pingable.Pingable {
152 > c.subscriptionLock.Lock()
153 > //nolint:staticcheck // SA2001 just checking if we can acquire the lock
154 > c.subscriptionLock.Unlock()
155 > return nil
156 > },
157 },
158 }
159 }
160
161 > func (c *Collection) pollForChanges(ctx context.Context) error { collection.go
162 > interval := DynamicConfigSubscriptionPollInterval.Get(c)
163 > for ctx.Err() == nil {
164 > util.InterruptibleSleep(ctx, interval())
165 > c.pollOnce()
166 > }
167 > return ctx.Err() collection.go
168 }
169
170 > func (c *Collection) pollOnce() { collection.go
171 > c.subscriptionLock.Lock()
172 > defer c.subscriptionLock.Unlock()
173 >
174 > for key, subs := range c.subscriptions {
175 > setting := queryRegistry(key)
176 > if setting == nil {
177 continue
178 }
179 > for _, sub := range subs { collection.go
180 cvs := c.client.GetValue(key)
181 setting.dispatchUpdate(c, sub, cvs)
212 cvs []ConstrainedValue,
213 precedence []Constraints,
214 > ) (*ConstrainedValue, error) { collection.go
215 > if len(cvs) == 0 {
216 > return nil, errKeyNotPresent collection.go
217 > } else if len(cvs) > constraintsCacheThreshold && len(cvs) <= math.MaxInt32 { collection.go
218 return findMatchWithCache(cache, cvs, precedence)
219 }
279 convert func(value any) (T, error),
280 precedence []Constraints,
281 > ) T { collection.go
282 > cvs := c.client.GetValue(key)
283 > v, _ := matchAndConvertCvs(c, key, def, convert, precedence, cvs)
284 > return v
285 > }
286
287 func matchAndConvertCvs[T any](
292 precedence []Constraints,
293 cvs []ConstrainedValue,
294 > ) (T, any) { collection.go
295 > cvp, err := findMatch(c.indexCache, cvs, precedence)
296 > if err != nil {
297 > // couldn't find a constrained match, use default collection.go
298 > return def, usingDefaultValue
299 > }
300
301 typedVal, err := convertWithCache(c, key, convert, cvp)
397 prec []Constraints,
398 callback func(T),
399 > ) (T, func()) { collection.go
400 > c.subscriptionLock.Lock()
401 > defer c.subscriptionLock.Unlock()
402 >
403 > // get one value immediately (note that subscriptionLock is held here so we can't race with
404 > // an update)
405 > cvs := c.client.GetValue(key)
406 > init, raw := matchAndConvertCvs(c, key, def, convert, prec, cvs)
407 >
408 > // As a convenience (and for efficiency), you can pass in a nil callback; we just return the
409 > // current value and skip the subscription. The cancellation func returned is also nil.
410 > if callback == nil {
411 return init, nil
412 }
413
414 > c.subscriptionIdx++ collection.go
415 > id := c.subscriptionIdx
416 >
417 > if c.subscriptions[key] == nil {
418 > c.subscriptions[key] = make(map[int]any)
419 > }
420
421 > c.subscriptions[key][id] = &subscription[T]{ collection.go
422 > prec: prec,
423 > f: callback,
424 > def: def,
425 > raw: raw,
426 > }
427 >
428 > return init, func() {
429 > c.subscriptionLock.Lock() collection.go
430 > defer c.subscriptionLock.Unlock()
431 > delete(c.subscriptions[key], id)
432 > }
433 }
434
676 // treat the fields independently), or the zero value of its type (if you want to treat the fields
677 // as a group and default unset fields to zero).
678 > func ConvertStructure[T any](def T) func(v any) (T, error) { collection.go
679 > return func(v any) (T, error) {
680 > // if we already have the right type, no conversion is necessary
681 > if typedV, ok := v.(T); ok {
682 return typedV, nil
683 }
685 // Deep-copy the default and decode over it. This allows using e.g. a struct with some
686 // default fields filled in and a config that only set some fields.
687 > out := deepCopyForMapstructure(def) collection.go
688 >
689 > dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
690 > Result: &out,
691 > DecodeHook: mapstructure.ComposeDecodeHookFunc(
692 > mapstructureHookDuration,
693 > mapstructureHookTimestamp,
694 > mapstructureHookProtoEnum,
695 > mapstructureHookGeneric,
696 > ),
697 > })
698 > if err != nil {
699 return out, err
700 }
701 > err = dec.Decode(v) collection.go
702 > return out, err
703 }
704 }
go.temporal.io/server/common/persistence/sql/cluster_metadata.go 110 covered LOC · 28 ranges

Open complete file

23 ctx context.Context,
24 request *p.InternalListClusterMetadataRequest,
25 > ) (*p.InternalListClusterMetadataResponse, error) { cluster_metadata.go
26 > var clusterName string
27 > if request.NextPageToken != nil {
28 err := gobDeserialize(request.NextPageToken, &clusterName)
29 if err != nil {
32 }
33
34 > rows, err := s.DB.ListClusterMetadata(ctx, &sqlplugin.ClusterMetadataFilter{ClusterName: clusterName, PageSize: &request.PageSize}) cluster_metadata.go
35 > if err != nil {
36 if err == sql.ErrNoRows {
37 return &p.InternalListClusterMetadataResponse{}, nil
40 }
41
42 > var clusterMetadata []*p.InternalGetClusterMetadataResponse cluster_metadata.go
43 > for _, row := range rows {
44 > resp := &p.InternalGetClusterMetadataResponse{
45 > ClusterMetadata: p.NewDataBlob(row.Data, row.DataEncoding),
46 > Version: row.Version,
47 > }
48 > clusterMetadata = append(clusterMetadata, resp)
49 > }
50
51 > resp := &p.InternalListClusterMetadataResponse{ClusterMetadata: clusterMetadata} cluster_metadata.go
52 > if len(rows) >= request.PageSize {
53 nextPageToken, err := gobSerialize(rows[len(rows)-1].ClusterName)
54 if err != nil {
63 ctx context.Context,
64 request *p.InternalGetClusterMetadataRequest,
65 > ) (*p.InternalGetClusterMetadataResponse, error) { cluster_metadata.go
66 > row, err := s.DB.GetClusterMetadata(ctx, &sqlplugin.ClusterMetadataFilter{ClusterName: request.ClusterName})
67 >
68 > if err != nil {
69 > return nil, convertCommonErrors("GetClusterMetadata", err)
70 > }
71
72 > return &p.InternalGetClusterMetadataResponse{ cluster_metadata.go
73 > ClusterMetadata: p.NewDataBlob(row.Data, row.DataEncoding),
74 > Version: row.Version,
75 > }, nil
76 }
77
79 ctx context.Context,
80 request *p.InternalSaveClusterMetadataRequest,
81 > ) (bool, error) { cluster_metadata.go
82 > err := s.txExecute(ctx, "SaveClusterMetadata", func(tx sqlplugin.Tx) error {
83 > oldClusterMetadata, err := tx.WriteLockGetClusterMetadata(
84 > ctx,
85 > &sqlplugin.ClusterMetadataFilter{ClusterName: request.ClusterName})
86 > var lastVersion int64
87 > if err != nil {
88 > if err != sql.ErrNoRows {
89 return serviceerror.NewUnavailablef("SaveClusterMetadata operation failed. Error %v", err)
90 }
92 lastVersion = oldClusterMetadata.Version
93 }
94 > if request.Version != lastVersion { cluster_metadata.go
95 return serviceerror.NewUnavailablef("SaveClusterMetadata encountered version mismatch, expected %v but got %v.",
96 request.Version, oldClusterMetadata.Version)
97 }
98 > _, err = tx.SaveClusterMetadata(ctx, &sqlplugin.ClusterMetadataRow{ cluster_metadata.go
99 > ClusterName: request.ClusterName,
100 > Data: request.ClusterMetadata.Data,
101 > DataEncoding: request.ClusterMetadata.EncodingType.String(),
102 > Version: request.Version,
103 > })
104 > if err != nil {
105 return convertCommonErrors("SaveClusterMetadata", err)
106 }
107 > return nil cluster_metadata.go
108 })
109
110 > if err != nil { cluster_metadata.go
111 return false, serviceerror.NewUnavailable(err.Error())
112 }
113 > return true, nil cluster_metadata.go
114 }
115
129 ctx context.Context,
130 request *p.GetClusterMembersRequest,
131 > ) (*p.GetClusterMembersResponse, error) { cluster_metadata.go
132 > var lastSeenHostId []byte
133 > if len(request.NextPageToken) == 16 {
134 lastSeenHostId = request.NextPageToken
135 > } else if len(request.NextPageToken) > 0 { cluster_metadata.go
136 return nil, serviceerror.NewInternal("page token is corrupted.")
137 }
138
139 > now := time.Now().UTC() cluster_metadata.go
140 > filter := &sqlplugin.ClusterMembershipFilter{
141 > HostIDEquals: request.HostIDEquals,
142 > RoleEquals: request.RoleEquals,
143 > RecordExpiryAfter: now,
144 > SessionStartedAfter: request.SessionStartedAfter,
145 > MaxRecordCount: request.PageSize,
146 > }
147 >
148 > if lastSeenHostId != nil && filter.HostIDEquals == nil {
149 filter.HostIDGreaterThan = lastSeenHostId
150 }
151
152 > if request.LastHeartbeatWithin > 0 { cluster_metadata.go
153 > filter.LastHeartbeatAfter = now.Add(-request.LastHeartbeatWithin)
154 > }
155
156 > if request.RPCAddressEquals != nil { cluster_metadata.go
157 filter.RPCAddressEquals = request.RPCAddressEquals.String()
158 }
159
160 > rows, err := s.DB.GetClusterMembers(ctx, filter) cluster_metadata.go
161 >
162 > if err != nil {
163 return nil, convertCommonErrors("GetClusterMembers", err)
164 }
165
166 > convertedRows := make([]*p.ClusterMember, 0, len(rows)) cluster_metadata.go
167 > for _, row := range rows {
168 > convertedRows = append(convertedRows, &p.ClusterMember{ cluster_metadata.go
169 > HostID: row.HostID,
170 > Role: row.Role,
171 > RPCAddress: net.ParseIP(row.RPCAddress),
172 > RPCPort: row.RPCPort,
173 > SessionStart: row.SessionStart,
174 > LastHeartbeat: row.LastHeartbeat,
175 > RecordExpiry: row.RecordExpiry,
176 > })
177 > }
178
179 > var nextPageToken []byte cluster_metadata.go
180 > if request.PageSize > 0 && len(rows) == request.PageSize {
181 lastRow := rows[len(rows)-1]
182 nextPageToken = lastRow.HostID
183 }
184
185 > return &p.GetClusterMembersResponse{ActiveMembers: convertedRows, NextPageToken: nextPageToken}, nil cluster_metadata.go
186 }
187
189 ctx context.Context,
190 request *p.UpsertClusterMembershipRequest,
191 > ) error { cluster_metadata.go
192 > now := time.Now().UTC()
193 > recordExpiry := now.Add(request.RecordExpiry)
194 > _, err := s.DB.UpsertClusterMembership(ctx, &sqlplugin.ClusterMembershipRow{
195 > Role: request.Role,
196 > HostID: request.HostID,
197 > RPCAddress: request.RPCAddress.String(),
198 > RPCPort: request.RPCPort,
199 > SessionStart: request.SessionStart,
200 > LastHeartbeat: now,
201 > RecordExpiry: recordExpiry})
202 >
203 > if err != nil {
204 return convertCommonErrors("UpsertClusterMembership", err)
205 }
206
207 > return nil cluster_metadata.go
208 }
209
211 ctx context.Context,
212 request *p.PruneClusterMembershipRequest,
213 > ) error { cluster_metadata.go
214 > _, err := s.DB.PruneClusterMembership(
215 > ctx,
216 > &sqlplugin.PruneClusterMembershipFilter{
217 > PruneRecordsBefore: time.Now().UTC(),
218 > },
219 > )
220 >
221 > if err != nil {
222 return convertCommonErrors("PruneClusterMembership", err)
223 }
224
225 > return nil cluster_metadata.go
226 }
227
230 logger log.Logger,
231 serializer serialization.Serializer,
232 > ) (p.ClusterMetadataStore, error) { cluster_metadata.go
233 > return &sqlClusterMetadataManager{
234 > SqlStore: NewSQLStore(db, logger, serializer),
235 > }, nil
236 > }
go.temporal.io/server/common/util.go 107 covered LOC · 25 ranges

Open complete file

135 // Returns true if the Wait() call succeeded before the timeout
136 // Returns false if the Wait() did not return before the timeout
137 > func AwaitWaitGroup(wg *sync.WaitGroup, timeout time.Duration) bool { util.go
138 > return BlockWithTimeout(wg.Wait, timeout)
139 > }
140
141 // BlockWithTimeout invokes fn and waits for it to complete until the timeout.
142 // Returns true if the call completed before the timeout, otherwise returns false.
143 // fn is expected to be a blocking call and will continue to occupy a goroutine until it finally completes.
144 > func BlockWithTimeout(fn func(), timeout time.Duration) bool { util.go
145 > doneC := make(chan struct{})
146 >
147 > go func() {
148 > fn()
149 > close(doneC)
150 > }()
151
152 > timer := time.NewTimer(timeout) util.go
153 > defer timer.Stop()
154 > select {
155 > case <-doneC:
156 > return true
157 case <-timer.C:
158 return false
161
162 // CreatePersistenceClientRetryPolicy creates a retry policy for calls to persistence
163 > func CreatePersistenceClientRetryPolicy() backoff.RetryPolicy { util.go
164 > return backoff.NewExponentialRetryPolicy(persistenceClientRetryInitialInterval).
165 > WithMaximumAttempts(persistenceClientRetryMaxAttempts)
166 > }
167
168 // CreateFrontendClientRetryPolicy creates a retry policy for calls to frontend service
169 > func CreateFrontendClientRetryPolicy() backoff.RetryPolicy { util.go
170 > return backoff.NewExponentialRetryPolicy(frontendClientRetryInitialInterval).
171 > WithMaximumAttempts(frontendClientRetryMaxAttempts)
172 > }
173
174 // CreateHistoryClientRetryPolicy creates a retry policy for calls to history service.
177 // default 1-minute expiration interval and the caller's context. Other errors (and all
178 // errors when the flag is off) follow the standard cap.
179 > func CreateHistoryClientRetryPolicy(retryUnboundedOnSystemResourceExhausted func() bool) backoff.RetryPolicy { util.go
180 > return newClientRetryPolicy(historyClientRetryInitialInterval, historyClientRetryMaxAttempts, retryUnboundedOnSystemResourceExhausted)
181 > }
182
183 // CreateMatchingClientRetryPolicy creates a retry policy for calls to matching service.
186 // default 1-minute expiration interval and the caller's context. Other errors (and all
187 // errors when the flag is off) follow the standard cap.
188 > func CreateMatchingClientRetryPolicy(retryUnboundedOnSystemResourceExhausted func() bool) backoff.RetryPolicy { util.go
189 > return newClientRetryPolicy(matchingClientRetryInitialInterval, matchingClientRetryMaxAttempts, retryUnboundedOnSystemResourceExhausted)
190 > }
191
192 > func newClientRetryPolicy(initialInterval time.Duration, maxAttempts int, retryUnboundedOnSystemResourceExhausted func() bool) backoff.RetryPolicy { util.go
193 > capped := backoff.NewExponentialRetryPolicy(initialInterval).
194 > WithMaximumAttempts(maxAttempts)
195 > // No max-attempts cap; bounded by the default 1-minute expiration interval
196 > // and the caller's context.
197 > extended := backoff.NewExponentialRetryPolicy(initialInterval)
198 > predicate := func(err error) bool {
199 > return retryUnboundedOnSystemResourceExhausted() && isSystemResourceExhausted(err)
200 > }
201 > return backoff.NewConditionalRetryPolicy(predicate, extended, capped)
202 }
203
210
211 // CreateMatchingClientLongPollRetryPolicy creates a retry policy for poll calls to matching service
212 > func CreateMatchingClientLongPollRetryPolicy() backoff.RetryPolicy { util.go
213 > // no maximum attempts, using default expiration interval of 1 minute
214 > return backoff.NewExponentialRetryPolicy(matchingClientRetryInitialInterval)
215 > }
216
217 // CreateFrontendHandlerRetryPolicy creates a retry policy for calls to frontend service
218 > func CreateFrontendHandlerRetryPolicy() backoff.RetryPolicy { util.go
219 > return backoff.NewExponentialRetryPolicy(frontendHandlerRetryInitialInterval).
220 > WithMaximumInterval(frontendHandlerRetryMaxInterval).
221 > WithMaximumAttempts(frontendHandlerRetryMaxAttempts)
222 > }
223
224 // CreateHistoryHandlerRetryPolicy creates a retry policy for calls to history service
225 > func CreateHistoryHandlerRetryPolicy() backoff.RetryPolicy { util.go
226 > return backoff.NewExponentialRetryPolicy(historyHandlerRetryInitialInterval).
227 > WithMaximumAttempts(historyHandlerRetryMaxAttempts)
228 > }
229
230 // CreateMatchingHandlerRetryPolicy creates a retry policy for calls to matching service
231 > func CreateMatchingHandlerRetryPolicy() backoff.RetryPolicy { util.go
232 > return backoff.NewExponentialRetryPolicy(matchingHandlerRetryInitialInterval).
233 > WithMaximumAttempts(matchingHandlerRetryMaxAttempts)
234 > }
235
236 // CreateReadTaskRetryPolicy creates a retry policy for loading background tasks
237 > func CreateReadTaskRetryPolicy() backoff.RetryPolicy { util.go
238 > return backoff.NewExponentialRetryPolicy(readTaskRetryInitialInterval).
239 > WithMaximumInterval(readTaskRetryMaxInterval).
240 > WithExpirationInterval(readTaskRetryExpirationInterval)
241 > }
242
243 // CreateCompleteTaskRetryPolicy creates a retry policy for completing background tasks
249
250 // CreateTaskReschedulePolicy creates a retry policy for rescheduling task with errors not equal to ErrTaskRetry
251 > func CreateTaskReschedulePolicy() backoff.RetryPolicy { util.go
252 > return backoff.NewExponentialRetryPolicy(taskRescheduleInitialInterval).
253 > WithBackoffCoefficient(taskRescheduleBackoffCoefficient).
254 > WithMaximumInterval(taskRescheduleMaxInterval).
255 > WithExpirationInterval(backoff.NoInterval)
256 > }
257
258 // CreateDependencyTaskNotCompletedReschedulePolicy creates a retry policy for rescheduling task with
259 // ErrDependencyTaskNotCompleted
260 > func CreateDependencyTaskNotCompletedReschedulePolicy() backoff.RetryPolicy { util.go
261 > return backoff.NewExponentialRetryPolicy(dependencyTaskNotCompletedRescheduleInitialInterval).
262 > WithBackoffCoefficient(dependencyTaskNotCompletedRescheduleBackoffCoefficient).
263 > WithMaximumInterval(dependencyTaskNotCompletedRescheduleMaxInterval).
264 > WithExpirationInterval(backoff.NoInterval)
265 > }
266
267 // CreateTaskNotReadyReschedulePolicy creates a retry policy for rescheduling task with ErrTaskRetry
268 > func CreateTaskNotReadyReschedulePolicy() backoff.RetryPolicy { util.go
269 > return backoff.NewExponentialRetryPolicy(taskNotReadyRescheduleInitialInterval).
270 > WithBackoffCoefficient(taskNotReadyRescheduleBackoffCoefficient).
271 > WithMaximumInterval(taskNotReadyRescheduleMaxInterval).
272 > WithExpirationInterval(backoff.NoInterval)
273 > }
274
275 // CreateTaskResourceExhaustedReschedulePolicy creates a retry policy for rescheduling task with resource exhausted error
276 > func CreateTaskResourceExhaustedReschedulePolicy() backoff.RetryPolicy { util.go
277 > return backoff.NewExponentialRetryPolicy(taskResourceExhaustedRescheduleInitialInterval).
278 > WithBackoffCoefficient(taskResourceExhaustedRescheduleBackoffCoefficient).
279 > WithMaximumInterval(taskResourceExhaustedRescheduleMaxInterval).
280 > WithExpirationInterval(backoff.NoInterval)
281 > }
282
283 // CreateSdkClientFactoryRetryPolicy creates a retry policy to handle SdkClientFactory NewClient when frontend service is not ready
284 > func CreateSdkClientFactoryRetryPolicy() backoff.RetryPolicy { util.go
285 > return backoff.NewExponentialRetryPolicy(sdkClientFactoryRetryInitialInterval).
286 > WithMaximumInterval(sdkClientFactoryRetryMaxInterval).
287 > WithExpirationInterval(sdkClientFactoryRetryExpirationInterval)
288 > }
289
290 // IsPersistenceTransientError checks if the error is a transient persistence error
329
330 // IsContextCanceledErr checks if the error is context.Canceled or serviceerror.Canceled error
331 > func IsContextCanceledErr(err error) bool { util.go
332 > var canceledSvcErr *serviceerror.Canceled
333 > return errors.Is(err, context.Canceled) ||
334 > errors.As(err, &canceledSvcErr)
335 > }
336
337 // IsServiceClientTransientError checks if the error is a transient error.
338 > func IsServiceClientTransientError(err error) bool { util.go
339 > if IsServiceHandlerRetryableError(err) {
340 > return true util.go
341 > }
342
343 if isSystemResourceExhausted(err) {
354 }
355
356 > func IsServiceHandlerRetryableError(err error) bool { util.go
357 > if IsNamespaceHandoverError(err) {
358 return false
359 }
360
361 > switch err := err.(type) { util.go
362 case *serviceerror.Internal,
363 > *serviceerror.Unavailable: util.go
364 > return true
365 case *serviceerror.MultiOperationExecution:
366 for _, opErr := range err.OperationErrors() {
374 }
375
376 > func IsNamespaceHandoverError(err error) bool { util.go
377 > return err.Error() == ErrNamespaceHandover.Error()
378 > }
379
380 func IsStickyWorkerUnavailable(err error) bool {
go.temporal.io/server/chasm/registry.go 106 covered LOC · 48 ranges

Open complete file

51 }
52
53 > func NewRegistry(logger log.Logger) *Registry { registry.go
54 > return &Registry{
55 > libraries: make(map[string]Library),
56 > rcByFqn: make(map[string]*RegistrableComponent),
57 > rcByID: make(map[uint32]*RegistrableComponent),
58 > rcByGoType: make(map[reflect.Type]*RegistrableComponent),
59 > rtByFqn: make(map[string]*RegistrableTask),
60 > rtByID: make(map[uint32]*RegistrableTask),
61 > rtByGoType: make(map[reflect.Type]*RegistrableTask),
62 > rcContextValues: make(map[any]valueWithFqn),
63 > nexusServices: make(map[string]*nexus.Service),
64 > NexusEndpointProcessor: NewNexusEndpointProcessor(),
65 > logger: logger,
66 > }
67 > }
68
69 > func (r *Registry) Register(lib Library) error { registry.go
70 > if err := r.validateName(lib.Name()); err != nil {
71 return err
72 }
73 > if _, ok := r.libraries[lib.Name()]; ok { registry.go
74 return fmt.Errorf("library %s is already registered", lib.Name())
75 }
76 > r.libraries[lib.Name()] = lib registry.go
77 >
78 > for _, c := range lib.Components() {
79 > if err := r.registerComponent(lib, c); err != nil { registry.go
80 return err
81 }
82 }
83 > for _, t := range lib.Tasks() { registry.go
84 > if err := r.registerTask(lib, t); err != nil { registry.go
85 return err
86 }
87 }
88
89 > for _, svc := range lib.NexusServices() { registry.go
90 > if err := r.registerNexusService(svc); err != nil { registry.go
91 return err
92 }
93 }
94
95 > for _, svc := range lib.NexusServiceProcessors() { registry.go
96 > if err := r.NexusEndpointProcessor.RegisterServiceProcessor(svc); err != nil { registry.go
97 return err
98 }
99 }
100
101 > return nil registry.go
102 }
103
104 // RegisterServices registers all gRPC services from all registered libraries.
105 > func (r *Registry) RegisterServices(server *grpc.Server) { registry.go
106 > for _, lib := range r.libraries {
107 > lib.RegisterServices(server)
108 > }
109 }
110
235 lib namer,
236 rc *RegistrableComponent,
237 > ) error { registry.go
238 > if err := r.validate(rc); err != nil {
239 return err
240 }
241
242 > fqn, id, err := rc.registerToLibrary(lib) registry.go
243 > if err != nil {
244 return err
245 }
246
247 > if _, ok := r.rcByFqn[fqn]; ok { registry.go
248 return fmt.Errorf("component %s is already registered", fqn)
249 }
250
251 > if id == UnspecifiedArchetypeID { registry.go
252 return fmt.Errorf("component %s maps to a reserved archetype id %d, please use a different name", fqn, UnspecifiedArchetypeID)
253 }
254
255 > if existingComponent, ok := r.rcByID[id]; ok { registry.go
256 return fmt.Errorf("component ID %d collision between %s and %s", id, fqn, existingComponent.fqType())
257 }
258
259 > for key, value := range rc.contextValues { registry.go
260 > if existingValue, ok := r.rcContextValues[key]; ok { registry.go
261 return fmt.Errorf("context value key %v registered by component %s conflicts with component %s", key, fqn, existingValue.fqn)
262 }
263 > r.rcContextValues[key] = valueWithFqn{ registry.go
264 > v: value,
265 > fqn: fqn,
266 > }
267 }
268
269 // rc.goType implements Component interface; therefore, it must be a struct.
270 // This check to protect against the interface itself being registered.
271 > if !(rc.goType.Kind() == reflect.Struct || registry.go
272 > (rc.goType.Kind() == reflect.Pointer && rc.goType.Elem().Kind() == reflect.Struct)) {
273 return fmt.Errorf("component type %s must be struct or pointer to struct", rc.goType.String())
274 }
275 > if _, ok := r.rcByGoType[rc.goType]; ok { registry.go
276 return fmt.Errorf("component type %s is already registered", rc.goType.String())
277 }
278 > r.warnUnmanagedFields(fqn, rc) registry.go
279 >
280 > r.rcByFqn[fqn] = rc
281 > r.rcByID[id] = rc
282 > r.rcByGoType[rc.goType] = rc
283 > return nil
284 }
285
286 > func (r *Registry) validate(rc *RegistrableComponent) error { registry.go
287 > if err := r.validateName(rc.componentType); err != nil {
288 return err
289 }
290 > return r.validateVisibilityBusinessIDAlias(rc) registry.go
291 }
292
294 lib namer,
295 rt *RegistrableTask,
296 > ) error { registry.go
297 > if err := r.validateName(rt.taskType); err != nil {
298 return err
299 }
300
301 > fqn, id, err := rt.registerToLibrary(lib) registry.go
302 > if err != nil {
303 return err
304 }
305
306 > if _, ok := r.rtByFqn[fqn]; ok { registry.go
307 return fmt.Errorf("task %s is already registered", fqn)
308 }
309
310 > if existingTask, ok := r.rtByID[id]; ok { registry.go
311 return fmt.Errorf("task type ID %d collision between %s and %s", id, fqn, existingTask.fqType())
312 }
313
314 > if !(rt.goType.Kind() == reflect.Struct || registry.go
315 > (rt.goType.Kind() == reflect.Pointer && rt.goType.Elem().Kind() == reflect.Struct)) {
316 return fmt.Errorf("task type %s must be struct or pointer to struct", rt.goType.String())
317 }
318 > if _, ok := r.rtByGoType[rt.goType]; ok { registry.go
319 return fmt.Errorf("task type %s is already registered", rt.goType.String())
320 }
321 > if !(rt.componentGoType.Kind() == reflect.Interface || registry.go
322 > (rt.componentGoType.Kind() == reflect.Struct ||
323 > (rt.componentGoType.Kind() == reflect.Pointer && rt.componentGoType.Elem().Kind() == reflect.Struct)) &&
324 > rt.componentGoType.AssignableTo(reflect.TypeFor[Component]())) {
325 return fmt.Errorf("component type %s must be and interface or struct that implements Component interface", rt.componentGoType.String())
326 }
327
328 > r.rtByFqn[fqn] = rt registry.go
329 > r.rtByID[id] = rt
330 > r.rtByGoType[rt.goType] = rt
331 > return nil
332 }
333
334 > func (r *Registry) validateName(n string) error { registry.go
335 > if n == "" {
336 return errors.New("name must not be empty")
337 }
338 > if !nameValidator.MatchString(n) { registry.go
339 return fmt.Errorf("name %s is invalid. name must follow golang identifier rules: %s", n, nameValidator.String())
340 }
341 > return nil registry.go
342 }
343
344 > func (r *Registry) validateVisibilityBusinessIDAlias(rc *RegistrableComponent) error { registry.go
345 > if !hasVisibilityField(rc.goType) {
346 > return nil registry.go
347 > }
348 // Archetypes that contain a Field[*Visibility] must specify WithBusinessIDAlias.
349 > if !rc.hasBusinessIDAlias() { registry.go
350 return fmt.Errorf("component %s has Field[*Visibility] but no businessID alias; use WithBusinessIDAlias option", rc.componentType)
351 }
352 > return nil registry.go
353 }
354
355 > func (r *Registry) warnUnmanagedFields(fqn string, rc *RegistrableComponent) { registry.go
356 > var unmanagedFields []string
357 > for f := range unmanagedFieldsOf(rc.goType) {
358 > unmanagedFields = append(unmanagedFields, fmt.Sprintf("%s %s", f.name, f.typ)) registry.go
359 > }
360 > if len(unmanagedFields) > 0 { registry.go
361 > r.logger.Info(fmt.Sprintf( registry.go
362 > "Warning: CHASM component %s declares state fields that won't be managed by CHASM:\n\t%s",
363 > fqn,
364 > strings.Join(unmanagedFields, "\n\t")))
365 > }
366 }
367
368 > func (r *Registry) registerNexusService(svc *nexus.Service) error { registry.go
369 > if _, ok := r.nexusServices[svc.Name]; ok {
370 return fmt.Errorf("nexus service %s is already registered", svc.Name)
371 }
372 > r.nexusServices[svc.Name] = svc registry.go
373 > return nil
374 }
375
376 // NexusServices returns all registered Nexus services.
377 > func (r *Registry) NexusServices() map[string]*nexus.Service { registry.go
378 > // Return a copy to prevent external modification
379 > services := make(map[string]*nexus.Service, len(r.nexusServices))
380 > maps.Copy(services, r.nexusServices)
381 > return services
382 > }
383
384 func (r *Registry) componentContextValue(key any) any {
go.temporal.io/server/service/frontend/workflow_handler.go 106 covered LOC · 7 ranges

Open complete file

339 workerDeploymentReadRateLimiter quotas.RequestRateLimiter,
340 validator *workflow.RequestValidator,
341 > ) *WorkflowHandler { workflow_handler.go
342 > handler := &WorkflowHandler{
343 > ActivityHandler: activityHandler,
344 > NexusOperationHandler: nexusOperationHandler,
345 > status: common.DaemonStatusInitialized,
346 > callbackValidator: callbackValidator,
347 > config: config,
348 > tokenSerializer: tasktoken.NewSerializer(),
349 > versionChecker: headers.NewDefaultVersionChecker(),
350 > namespaceHandler: newNamespaceHandler(
351 > logger,
352 > persistenceMetadataManager,
353 > namespaceRegistry,
354 > clusterMetadata,
355 > nsreplication.NewReplicator(namespaceReplicationQueue, logger),
356 > archivalMetadata,
357 > archiverProvider,
358 > timeSource,
359 > config,
360 > ),
361 > getDefaultWorkflowRetrySettings: config.DefaultWorkflowRetryPolicy,
362 > visibilityMgr: visibilityMgr,
363 > logger: logger,
364 > throttledLogger: throttledLogger,
365 > persistenceExecutionName: persistenceExecutionName,
366 > clusterMetadataManager: clusterMetadataManager,
367 > clusterMetadata: clusterMetadata,
368 > historyClient: historyClient,
369 > matchingClient: matchingClient,
370 > workerDeploymentClient: workerDeploymentClient,
371 > schedulerClient: schedulerClient,
372 > archiverProvider: archiverProvider,
373 > payloadSerializer: payloadSerializer,
374 > namespaceRegistry: namespaceRegistry,
375 > saProvider: saProvider,
376 > saMapperProvider: saMapperProvider,
377 > saValidator: saValidator,
378 > archivalMetadata: archivalMetadata,
379 > healthServer: healthServer,
380 > overrides: NewOverrides(),
381 > membershipMonitor: membershipMonitor,
382 > healthInterceptor: healthInterceptor,
383 > scheduleSpecBuilder: scheduleSpecBuilder,
384 > outstandingPollers: collection.NewSyncMap[string, collection.SyncMap[string, context.CancelFunc]](),
385 > httpEnabled: httpEnabled,
386 > registry: registry,
387 > workerDeploymentReadRateLimiter: workerDeploymentReadRateLimiter,
388 > validator: validator,
389 > }
390 >
391 > return handler
392 > }
393
394 // Start starts the handler
395 > func (wh *WorkflowHandler) Start() { workflow_handler.go
396 > if atomic.CompareAndSwapInt32(
397 > &wh.status,
398 > common.DaemonStatusInitialized,
399 > common.DaemonStatusStarted,
400 > ) {
401 > // Start in NOT_SERVING state and switch to SERVING after membership is ready
402 > wh.healthServer.SetServingStatus(WorkflowServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
403 > go func() {
404 > _ = wh.membershipMonitor.WaitUntilInitialized(context.Background())
405 > wh.healthServer.SetServingStatus(WorkflowServiceName, healthpb.HealthCheckResponse_SERVING)
406 > wh.healthInterceptor.SetHealthy(true)
407 > wh.logger.Info("Frontend is now healthy")
408 > }()
409
410 > wh.namespaceRegistry.RegisterStateChangeCallback(wh, func(ns *namespace.Namespace, deletedFromDb bool) { workflow_handler.go
411 > if deletedFromDb {
412 return
413 }
414
415 > if ns.IsGlobalNamespace() && workflow_handler.go
416 > ns.ReplicationPolicy() == namespace.ReplicationPolicyMultiCluster &&
417 > //nolint:forbidigo // namespace state-change callback; cancels all pollers on ns deactivation
418 > !ns.ActiveInCluster(wh.clusterMetadata.GetCurrentClusterName()) {
419 pollers, ok := wh.outstandingPollers.Get(ns.ID().String())
420 if ok {
429
430 // Stop stops the handler
431 > func (wh *WorkflowHandler) Stop() { workflow_handler.go
432 > if atomic.CompareAndSwapInt32(
433 > &wh.status,
434 > common.DaemonStatusStarted,
435 > common.DaemonStatusStopped,
436 > ) {
437 > wh.namespaceRegistry.UnregisterStateChangeCallback(wh)
438 > wh.healthServer.SetServingStatus(WorkflowServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
439 > wh.healthInterceptor.SetHealthy(false)
440 > }
441 }
442
3463
3464 // GetSystemInfo returns information about the Temporal system.
3465 > func (wh *WorkflowHandler) GetSystemInfo(ctx context.Context, request *workflowservice.GetSystemInfoRequest) (_ *workflowservice.GetSystemInfoResponse, retError error) { workflow_handler.go
3466 > defer log.CapturePanic(wh.logger, &retError)
3467 >
3468 > if request == nil {
3469 return nil, errRequestNotSet
3470 }
3471
3472 > return &workflowservice.GetSystemInfoResponse{ workflow_handler.go
3473 > ServerVersion: headers.ServerVersion,
3474 > // Capabilities should be added as needed. In many cases, capabilities are
3475 > // hardcoded boolean true values since older servers will respond with a
3476 > // form of this message without the field which is implied false.
3477 > Capabilities: &workflowservice.GetSystemInfoResponse_Capabilities{
3478 > SignalAndQueryHeader: true,
3479 > InternalErrorDifferentiation: true,
3480 > ActivityFailureIncludeHeartbeat: true,
3481 > SupportsSchedules: true,
3482 > EncodedFailureAttributes: true,
3483 > UpsertMemo: true,
3484 > EagerWorkflowStart: true,
3485 > SdkMetadata: true,
3486 > BuildIdBasedVersioning: true,
3487 > CountGroupByExecutionStatus: true,
3488 > Nexus: wh.httpEnabled,
3489 > ServerScaledDeployments: true,
3490 > },
3491 > }, nil
3492 }
3493
go.temporal.io/server/chasm/search_attribute.go 105 covered LOC · 16 ranges

Open complete file

136 }
137
138 > func newSearchAttributeFieldBool(index int) SearchAttributeFieldBool { search_attribute.go
139 > return SearchAttributeFieldBool{
140 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_BOOL, index),
141 > }
142 > }
143
144 // SearchAttributeFieldDateTime is a search attribute field for a datetime value.
147 }
148
149 > func newSearchAttributeFieldDateTime(index int) SearchAttributeFieldDateTime { search_attribute.go
150 > return SearchAttributeFieldDateTime{
151 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_DATETIME, index),
152 > }
153 > }
154
155 // SearchAttributeFieldInt is a search attribute field for an integer value.
158 }
159
160 > func newSearchAttributeFieldInt(index int) SearchAttributeFieldInt { search_attribute.go
161 > return SearchAttributeFieldInt{
162 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_INT, index),
163 > }
164 > }
165
166 // SearchAttributeFieldDouble is a search attribute field for a double value.
169 }
170
171 > func newSearchAttributeFieldDouble(index int) SearchAttributeFieldDouble { search_attribute.go
172 > return SearchAttributeFieldDouble{
173 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_DOUBLE, index),
174 > }
175 > }
176
177 // SearchAttributeFieldKeyword is a search attribute field for a keyword value.
180 }
181
182 > func newSearchAttributeFieldKeyword(index int) SearchAttributeFieldKeyword { search_attribute.go
183 > return SearchAttributeFieldKeyword{
184 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_KEYWORD, index),
185 > }
186 > }
187
188 > func newSearchAttributeFieldLowCardinalityKeyword(index int) SearchAttributeFieldKeyword { search_attribute.go
189 > return SearchAttributeFieldKeyword{
190 > field: fmt.Sprintf("%s%s%02d", sadefs.ReservedPrefix, "LowCardinalityKeyword", index),
191 > }
192 > }
193
194 // SearchAttributeFieldKeywordList is a search attribute field for a keyword list value.
197 }
198
199 > func newSearchAttributeFieldKeywordList(index int) SearchAttributeFieldKeywordList { search_attribute.go
200 > return SearchAttributeFieldKeywordList{
201 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST, index),
202 > }
203 > }
204
205 // SearchAttributeFieldText is a search attribute field for a text value.
214 }
215
216 > func resolveFieldName(valueType enumspb.IndexedValueType, index int) string { search_attribute.go
217 > // Columns are named like TemporalBool01, TemporalDatetime01, TemporalDouble01, TemporalInt01.
218 > return fmt.Sprintf("%s%s%02d", sadefs.ReservedPrefix, valueType.String(), index)
219 > }
220
221 > func (s searchAttributeDefinition) definition() searchAttributeDefinition { search_attribute.go
222 > return s
223 > }
224
225 // SearchAttributeBool is a search attribute for a boolean value.
239 }
240
241 > func newSearchAttributeBoolByField(field string) SearchAttributeBool { search_attribute.go
242 > return SearchAttributeBool{
243 > searchAttributeDefinition: searchAttributeDefinition{
244 > alias: field,
245 > field: field,
246 > valueType: enumspb.INDEXED_VALUE_TYPE_BOOL,
247 > },
248 > }
249 > }
250
251 // Value sets the boolean value of the search attribute.
266
267 // NewSearchAttributeDateTime creates a new date time search attribute given a predefined chasm field
268 > func NewSearchAttributeDateTime(alias string, datetimeField SearchAttributeFieldDateTime) SearchAttributeDateTime { search_attribute.go
269 > return SearchAttributeDateTime{
270 > searchAttributeDefinition: searchAttributeDefinition{
271 > alias: alias,
272 > field: datetimeField.field,
273 > valueType: enumspb.INDEXED_VALUE_TYPE_DATETIME,
274 > },
275 > }
276 > }
277
278 > func newSearchAttributeDateTimeByField(field string) SearchAttributeDateTime { search_attribute.go
279 > return SearchAttributeDateTime{
280 > searchAttributeDefinition: searchAttributeDefinition{
281 > alias: field,
282 > field: field,
283 > valueType: enumspb.INDEXED_VALUE_TYPE_DATETIME,
284 > },
285 > }
286 > }
287
288 // Value sets the date time value of the search attribute.
303
304 // NewSearchAttributeInt creates a new integer search attribute given a predefined chasm field
305 > func NewSearchAttributeInt(alias string, intField SearchAttributeFieldInt) SearchAttributeInt { search_attribute.go
306 > return SearchAttributeInt{
307 > searchAttributeDefinition: searchAttributeDefinition{
308 > alias: alias,
309 > field: intField.field,
310 > valueType: enumspb.INDEXED_VALUE_TYPE_INT,
311 > },
312 > }
313 > }
314
315 // Value sets the integer value of the search attribute.
367
368 // NewSearchAttributeKeyword creates a new keyword search attribute given a predefined chasm field
369 > func NewSearchAttributeKeyword(alias string, keywordField SearchAttributeFieldKeyword) SearchAttributeKeyword { search_attribute.go
370 > return SearchAttributeKeyword{
371 > searchAttributeDefinition: searchAttributeDefinition{
372 > alias: alias,
373 > field: keywordField.field,
374 > valueType: enumspb.INDEXED_VALUE_TYPE_KEYWORD,
375 > },
376 > }
377 > }
378
379 > func newSearchAttributeKeywordByField(field string) SearchAttributeKeyword { search_attribute.go
380 > return SearchAttributeKeyword{
381 > searchAttributeDefinition: searchAttributeDefinition{
382 > alias: field,
383 > field: field,
384 > valueType: enumspb.INDEXED_VALUE_TYPE_KEYWORD,
385 > },
386 > }
387 > }
388
389 // Value sets the string value of the search attribute.
414 }
415
416 > func newSearchAttributeKeywordListByField(field string) SearchAttributeKeywordList { search_attribute.go
417 > return SearchAttributeKeywordList{
418 > searchAttributeDefinition: searchAttributeDefinition{
419 > alias: field,
420 > field: field,
421 > valueType: enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST,
422 > },
423 > }
424 > }
425
426 // Value sets the string list value of the search attribute.
go.temporal.io/server/common/log/tag/tags.go 105 covered LOC · 34 ranges

Open complete file

30
31 // Operation returns tag for Operation
32 > func Operation(operation string) ZapTag { tags.go
33 > return NewStringTag("operation", operation)
34 > }
35
36 // Error returns tag for Error
37 > func Error(err error) ZapTag { tags.go
38 > return ZapTag{
39 > // NOTE: zap already chosen "error" as key
40 > field: zap.Error(err),
41 > }
42 > }
43
44 // ServiceErrorType returns tag for ServiceErrorType
45 > func ServiceErrorType(err error) ZapTag { tags.go
46 > return NewStringTag("service-error-type", util.ErrorType(err))
47 > }
48
49 // IsRetryable returns tag for IsRetryable
70
71 // WorkflowAction returns tag for WorkflowAction
72 > func workflowAction(action string) ZapTag { tags.go
73 > return NewStringTag("wf-action", action)
74 > }
75
76 // WorkflowListFilterType returns tag for WorkflowListFilterType
77 > func workflowListFilterType(listFilterType string) ZapTag { tags.go
78 > return NewStringTag("wf-list-filter-type", listFilterType)
79 > }
80
81 // general
108 // WorkflowID returns tag for WorkflowID
109 // TODO: Rename to BusinessID.
110 > func WorkflowID(workflowID string) ZapTag { tags.go
111 > return NewStringTag(WorkflowIDKey, workflowID)
112 > }
113
114 // WorkflowType returns tag for WorkflowType
115 > func WorkflowType(wfType string) ZapTag { tags.go
116 > return NewStringTag("wf-type", wfType)
117 > }
118
119 // WorkflowState returns tag for WorkflowState
192
193 // WorkflowNamespace returns tag for WorkflowNamespace
194 > func WorkflowNamespace(namespace string) ZapTag { tags.go
195 > return NewStringTag("wf-namespace", namespace)
196 > }
197
198 // WorkflowNamespaceIDs returns tag for WorkflowNamespaceIDs
376
377 // Component returns tag for Component
378 > func component(component string) ZapTag { tags.go
379 > return NewStringTag("component", component)
380 > }
381
382 // Lifecycle returns tag for Lifecycle
383 > func lifecycle(lifecycle string) ZapTag { tags.go
384 > return NewStringTag("lifecycle", lifecycle)
385 > }
386
387 // StoreOperation returns tag for StoreOperation
388 > func storeOperation(storeOperation string) ZapTag { tags.go
389 > return NewStringTag("store-operation", storeOperation)
390 > }
391
392 // OperationResult returns tag for OperationResult
393 > func operationResult(operationResult string) ZapTag { tags.go
394 > return NewStringTag("operation-result", operationResult)
395 > }
396
397 // ErrorType returns tag for ErrorType
401
402 // errorType returns tag for ErrorType given a string
403 > func errorType(errorType string) ZapTag { tags.go
404 > return NewStringTag("error-type", errorType)
405 > }
406
407 // Shardupdate returns tag for Shardupdate
408 > func shardupdate(shardupdate string) ZapTag { tags.go
409 > return NewStringTag("shard-update", shardupdate)
410 > }
411
412 // scope returns a tag for scope
413 // Pre-defined scope tags are in values.go.
414 > func scope(scope string) ZapTag { tags.go
415 > return NewStringTag("scope", scope)
416 > }
417
418 // general
419
420 // Service returns tag for Service
421 > func Service(sv primitives.ServiceName) ZapTag { tags.go
422 > return NewStringTag("service", string(sv))
423 > }
424
425 // Addresses returns tag for Addresses
426 > func Addresses(ads []string) ZapTag { tags.go
427 > return NewStringsTag("addresses", ads)
428 > }
429
430 // ListenerName returns tag for ListenerName
434
435 // Address return tag for Address
436 > func Address(ad string) ZapTag { tags.go
437 > return NewStringTag("address", ad)
438 > }
439
440 // HostID return tag for HostID
441 > func HostID(hid string) ZapTag { tags.go
442 > return NewStringTag("hostId", hid)
443 > }
444
445 // Env return tag for runtime environment
449
450 // Key returns tag for Key
451 > func Key(k string) ZapTag { tags.go
452 > return NewStringTag("key", k)
453 > }
454
455 // Name returns tag for Name
456 > func Name(k string) ZapTag { tags.go
457 > return NewStringTag("name", k)
458 > }
459
460 // Value returns tag for Value
461 > func Value(v any) ZapTag { tags.go
462 > return NewAnyTag("value", v)
463 > }
464
465 // ValueType returns tag for ValueType
479
480 // Host returns tag for Host
481 > func Host(h string) ZapTag { tags.go
482 > return NewStringTag("host", h)
483 > }
484
485 // Port returns tag for Port
486 > func Port(p int) ZapTag { tags.go
487 > return NewInt("port", p)
488 > }
489
490 // CursorTimestamp returns tag for CursorTimestamp
524
525 // Number returns tag for Number
526 > func Number(n int64) ZapTag { tags.go
527 > return NewInt64("number", n)
528 > }
529
530 // NextNumber returns tag for NextNumber
531 > func NextNumber(n int64) ZapTag { tags.go
532 > return NewInt64("next-number", n)
533 > }
534
535 // ServerName returns tag for ServerName
553
554 // ShardID returns tag for ShardID
555 > func ShardID(shardID int32) ZapTag { tags.go
556 > return NewInt32("shard-id", shardID)
557 > }
558
559 // ShardTime returns tag for ShardTime
563
564 // PreviousShardRangeID returns tag for PreviousShardRangeID
565 > func PreviousShardRangeID(id int64) ZapTag { tags.go
566 > return NewInt64("previous-shard-range-id", id)
567 > }
568
569 // ShardRangeID returns tag for ShardRangeID
570 > func ShardRangeID(id int64) ZapTag { tags.go
571 > return NewInt64("shard-range-id", id)
572 > }
573
574 // ShardContextState returns tag for ShardContextState
605
606 // QueueReaderID returns tag for queue readerID
607 > func QueueReaderID(readerID int64) ZapTag { tags.go
608 > return NewInt64("queue-reader-id", readerID)
609 > }
610
611 // QueueAlert returns tag for queue alert
648
649 // NumberProcessed returns tag for NumberProcessed
650 > func NumberProcessed(n int) ZapTag { tags.go
651 > return NewInt("number-processed", n)
652 > }
653
654 // NumberDeleted returns tag for NumberDeleted
655 > func NumberDeleted(n int) ZapTag { tags.go
656 > return NewInt("number-deleted", n)
657 > }
658
659 // NumberChanged returns tag for NumberChanged
660 > func NumberChanged(n int) ZapTag { tags.go
661 > return NewInt("number-changed", n)
662 > }
663
664 // TimerTaskStatus returns tag for TimerTaskStatus
954
955 // BootstrapHostPorts returns tag for bootstrap host ports
956 > func BootstrapHostPorts(s string) ZapTag { tags.go
957 > return NewStringTag("bootstrap-hostports", s)
958 > }
959
960 // TLSCertFile returns tag for TLS cert file name
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/cluster_metadata.go 104 covered LOC · 21 ranges

Open complete file

55 ctx context.Context,
56 row *sqlplugin.ClusterMetadataRow,
57 > ) (sql.Result, error) { cluster_metadata.go
58 > if row.Version == 0 {
59 > return mdb.conn.ExecContext(ctx,
60 > insertClusterMetadataQry,
61 > constMetadataPartition,
62 > row.ClusterName,
63 > row.Data,
64 > row.DataEncoding,
65 > 1,
66 > )
67 > }
68 return mdb.conn.ExecContext(ctx,
69 updateClusterMetadataQry,
79 ctx context.Context,
80 filter *sqlplugin.ClusterMetadataFilter,
81 > ) ([]sqlplugin.ClusterMetadataRow, error) { cluster_metadata.go
82 > var err error
83 > var rows []sqlplugin.ClusterMetadataRow
84 > switch {
85 case len(filter.ClusterName) != 0:
86 err = mdb.conn.SelectContext(ctx,
91 filter.PageSize,
92 )
93 > default: cluster_metadata.go
94 > err = mdb.conn.SelectContext(ctx,
95 > &rows,
96 > listClusterMetadataQry,
97 > constMetadataPartition,
98 > filter.PageSize,
99 > )
100 }
101 > return rows, err cluster_metadata.go
102 }
103
105 ctx context.Context,
106 filter *sqlplugin.ClusterMetadataFilter,
107 > ) (*sqlplugin.ClusterMetadataRow, error) { cluster_metadata.go
108 > var row sqlplugin.ClusterMetadataRow
109 > err := mdb.conn.GetContext(ctx,
110 > &row,
111 > getClusterMetadataQry,
112 > constMetadataPartition,
113 > filter.ClusterName,
114 > )
115 > if err != nil {
116 > return nil, err
117 > }
118 > return &row, err
119 }
120
122 ctx context.Context,
123 filter *sqlplugin.ClusterMetadataFilter,
124 > ) (*sqlplugin.ClusterMetadataRow, error) { cluster_metadata.go
125 > var row sqlplugin.ClusterMetadataRow
126 > err := mdb.conn.GetContext(ctx,
127 > &row,
128 > writeLockGetClusterMetadataQry,
129 > constMetadataPartition,
130 > filter.ClusterName,
131 > )
132 > if err != nil {
133 > return nil, err
134 > }
135 return &row, err
136 }
151 ctx context.Context,
152 row *sqlplugin.ClusterMembershipRow,
153 > ) (sql.Result, error) { cluster_metadata.go
154 > return mdb.conn.ExecContext(ctx,
155 > templateUpsertActiveClusterMembership,
156 > constMembershipPartition,
157 > row.HostID,
158 > row.RPCAddress,
159 > row.RPCPort,
160 > row.Role,
161 > mdb.converter.ToSQLiteDateTime(row.SessionStart),
162 > mdb.converter.ToSQLiteDateTime(row.LastHeartbeat),
163 > mdb.converter.ToSQLiteDateTime(row.RecordExpiry))
164 > }
165
166 func (mdb *db) GetClusterMembers(
167 ctx context.Context,
168 filter *sqlplugin.ClusterMembershipFilter,
169 > ) ([]sqlplugin.ClusterMembershipRow, error) { cluster_metadata.go
170 > var queryString strings.Builder
171 > var operands []any
172 > queryString.WriteString(templateGetClusterMembership)
173 > operands = append(operands, constMembershipPartition)
174 >
175 > if filter.HostIDEquals != nil {
176 queryString.WriteString(templateWithHostIDSuffix)
177 operands = append(operands, filter.HostIDEquals)
178 }
179
180 > if filter.RPCAddressEquals != "" { cluster_metadata.go
181 queryString.WriteString(templateWithRPCAddressSuffix)
182 operands = append(operands, filter.RPCAddressEquals)
183 }
184
185 > if filter.RoleEquals != p.All { cluster_metadata.go
186 queryString.WriteString(templateWithRoleSuffix)
187 operands = append(operands, filter.RoleEquals)
188 }
189
190 > if !filter.LastHeartbeatAfter.IsZero() { cluster_metadata.go
191 > queryString.WriteString(templateWithHeartbeatSinceSuffix)
192 > operands = append(operands, filter.LastHeartbeatAfter)
193 > }
194
195 > if !filter.RecordExpiryAfter.IsZero() { cluster_metadata.go
196 > queryString.WriteString(templateWithRecordExpirySuffix)
197 > operands = append(operands, filter.RecordExpiryAfter)
198 > }
199
200 > if !filter.SessionStartedAfter.IsZero() { cluster_metadata.go
201 queryString.WriteString(templateWithSessionStartSuffix)
202 operands = append(operands, filter.SessionStartedAfter)
203 }
204
205 > if filter.HostIDGreaterThan != nil { cluster_metadata.go
206 queryString.WriteString(templateWithHostIDGreaterSuffix)
207 operands = append(operands, filter.HostIDGreaterThan)
208 }
209
210 > queryString.WriteString(templateWithOrderBySessionStartSuffix) cluster_metadata.go
211 >
212 > if filter.MaxRecordCount > 0 {
213 > queryString.WriteString(templateWithLimitSuffix) cluster_metadata.go
214 > operands = append(operands, filter.MaxRecordCount)
215 > }
216
217 > compiledQryString := queryString.String() cluster_metadata.go
218 >
219 > var rows []sqlplugin.ClusterMembershipRow
220 > if err := mdb.conn.SelectContext(ctx,
221 > &rows,
222 > compiledQryString,
223 > operands...,
224 > ); err != nil {
225 return nil, err
226 }
227 > for i := range rows { cluster_metadata.go
228 > rows[i].SessionStart = mdb.converter.FromSQLiteDateTime(rows[i].SessionStart) cluster_metadata.go
229 > rows[i].LastHeartbeat = mdb.converter.FromSQLiteDateTime(rows[i].LastHeartbeat)
230 > rows[i].RecordExpiry = mdb.converter.FromSQLiteDateTime(rows[i].RecordExpiry)
231 > }
232 > return rows, nil cluster_metadata.go
233 }
234
236 ctx context.Context,
237 filter *sqlplugin.PruneClusterMembershipFilter,
238 > ) (sql.Result, error) { cluster_metadata.go
239 > return mdb.conn.ExecContext(ctx,
240 > templatePruneStaleClusterMembership,
241 > constMembershipPartition,
242 > mdb.converter.ToSQLiteDateTime(filter.PruneRecordsBefore),
243 > )
244 > }
go.temporal.io/server/service/history/queues/scheduler.go 103 covered LOC · 14 ranges

Open complete file

100 metricsHandler metrics.Handler,
101 timeSource clock.TimeSource,
102 > ) Scheduler { scheduler.go
103 > var scheduler tasks.Scheduler[Executable]
104 >
105 > taskChannelKeyFn := func(e Executable) TaskChannelKey {
106 return TaskChannelKey{
107 NamespaceID: e.GetNamespaceID(),
109 }
110 }
111 > channelWeightFn := func(key TaskChannelKey) int { scheduler.go
112 namespaceWeights := options.ActiveNamespaceWeights
113 namespaceName := namespace.EmptyName
143 return weight
144 }
145 > channelWeightUpdateCh := make(chan struct{}, 1) scheduler.go
146 > fifoSchedulerOptions := &tasks.FIFOSchedulerOptions{
147 > QueueSize: prioritySchedulerProcessorQueueSize,
148 > WorkerCount: options.WorkerCount,
149 > }
150 >
151 > fifoScheduler := tasks.NewFIFOScheduler[Executable](
152 > fifoSchedulerOptions,
153 > logger,
154 > )
155 >
156 > // Wrap the FIFO scheduler with ExecutionAwareScheduler for sequential per-execution processing
157 > executionAwareScheduler := tasks.NewExecutionAwareScheduler[Executable](
158 > fifoScheduler,
159 > options.ExecutionAwareSchedulerOptions,
160 > executableQueueKeyFn,
161 > logger,
162 > metricsHandler,
163 > timeSource,
164 > )
165 >
166 > scheduler = tasks.NewInterleavedWeightedRoundRobinScheduler(
167 > tasks.InterleavedWeightedRoundRobinSchedulerOptions[Executable, TaskChannelKey]{
168 > TaskChannelKeyFn: taskChannelKeyFn,
169 > ChannelWeightFn: channelWeightFn,
170 > ChannelWeightUpdateCh: channelWeightUpdateCh,
171 > InactiveChannelDeletionDelay: options.InactiveNamespaceDeletionDelay,
172 > },
173 > executionAwareScheduler,
174 > logger,
175 > )
176 >
177 > return &schedulerImpl{
178 > Scheduler: scheduler,
179 > namespaceRegistry: namespaceRegistry,
180 > taskChannelKeyFn: taskChannelKeyFn,
181 > channelWeightFn: channelWeightFn,
182 > channelWeightUpdateCh: channelWeightUpdateCh,
183 > executionAwareScheduler: executionAwareScheduler,
184 > }
185 }
186
187 > func (s *schedulerImpl) Start() { scheduler.go
188 > if s.channelWeightUpdateCh != nil {
189 > s.namespaceRegistry.RegisterStateChangeCallback(s, func(ns *namespace.Namespace, deletedFromDb bool) {
190 > select {
191 > case s.channelWeightUpdateCh <- struct{}{}:
192 > default:
193 }
194 })
195 }
196 > s.Scheduler.Start() scheduler.go
197 }
198
199 > func (s *schedulerImpl) Stop() { scheduler.go
200 > if s.channelWeightUpdateCh != nil {
201 > s.namespaceRegistry.UnregisterStateChangeCallback(s)
202 >
203 > // note we can't close the channelWeightUpdateCh here
204 > // as callback may still be triggered even after unregister returns
205 > // due to race condition
206 > //
207 > // channelWeightFn is only not nil when using host level scheduler
208 > // so Stop is only called when host is shutting down, and we don't need
209 > // to worry about open channels
210 > }
211 > s.Scheduler.Stop()
212 }
213
214 > func (s *schedulerImpl) TaskChannelKeyFn() TaskChannelKeyFn { scheduler.go
215 > return s.taskChannelKeyFn
216 > }
217
218 // HandleBusyWorkflow implements BusyWorkflowHandler by delegating to the
230 }
231
232 > func (s *CommonSchedulerWrapper) TaskChannelKeyFn() TaskChannelKeyFn { scheduler.go
233 > return s.TaskKeyFn
234 > }
235
236 func NewRateLimitedScheduler(
244 logger log.Logger,
245 metricsHandler metrics.Handler,
246 > ) Scheduler { scheduler.go
247 > if delay := options.StartupDelay(); delay > 0 {
248 > delayedRateLimiter, err := quotas.NewDelayedRequestRateLimiter(
249 > rateLimiter,
250 > delay,
251 > timeSource,
252 > )
253 > if err != nil {
254 logger.Error("Failed to create delayed rate limited scheduler", tag.Error(err))
255 return baseScheduler
256 }
257
258 > rateLimiter = delayedRateLimiter scheduler.go
259 }
260
261 > taskQuotaRequestFn := func(e Executable) quotas.Request { scheduler.go
262 namespaceName, err := namespaceRegistry.GetNamespaceName(namespace.ID(e.GetNamespaceID()))
263 if err != nil {
266 return quotas.NewRequest(e.GetType().String(), taskSchedulerToken, namespaceName.String(), e.GetPriority().CallerType(), 0, "")
267 }
268 > taskMetricsTagsFn := func(e Executable) []metrics.Tag { scheduler.go
269 return append(
270 taskBaseMetricTags(e.GetTask(), namespaceRegistry, currentClusterName, chasmRegistry, GetTaskTypeTagValue),
273 }
274
275 > rateLimitedScheduler := tasks.NewRateLimitedScheduler[Executable]( scheduler.go
276 > baseScheduler,
277 > rateLimiter,
278 > timeSource,
279 > taskQuotaRequestFn,
280 > taskMetricsTagsFn,
281 > tasks.RateLimitedSchedulerOptions{
282 > Enabled: options.Enabled,
283 > EnableShadowMode: options.EnableShadowMode,
284 > },
285 > logger,
286 > metricsHandler,
287 > )
288 >
289 > return &rateLimitedSchedulerImpl{
290 > Scheduler: rateLimitedScheduler,
291 > baseScheduler: baseScheduler,
292 > }
293 }
294
301 }
302
303 > func (s *rateLimitedSchedulerImpl) TaskChannelKeyFn() TaskChannelKeyFn { scheduler.go
304 > return s.baseScheduler.TaskChannelKeyFn()
305 > }
306
307 // HandleBusyWorkflow implements BusyWorkflowHandler by delegating to the
go.temporal.io/server/common/membership/ringpop/factory.go 101 covered LOC · 28 ranges

Open complete file

65
66 // newFactory builds a ringpop factory
67 > func newFactory(params factoryParams) (*factory, error) { factory.go
68 > cfg := params.Config
69 > if cfg.BroadcastAddress != "" && net.ParseIP(cfg.BroadcastAddress) == nil {
70 return nil, fmt.Errorf("%w: %s", errMalformedBroadcastAddress, cfg.BroadcastAddress)
71 }
72
73 > if cfg.MaxJoinDuration == 0 { factory.go
74 cfg.MaxJoinDuration = defaultMaxJoinDuration
75 }
76
77 > return &factory{ factory.go
78 > Config: params.Config,
79 > ServiceName: params.ServiceName,
80 > ServicePortMap: params.ServicePortMap,
81 > Logger: params.Logger,
82 > MetadataManager: params.MetadataManager,
83 > RPCConfig: params.RPCConfig,
84 > TLSFactory: params.TLSFactory,
85 > DC: params.DC,
86 > }, nil
87 }
88
89 // getMonitor returns a membership monitor
90 > func (factory *factory) getMonitor() *monitor { factory.go
91 > factory.monOnce.Do(func() {
92 > ctx, cancel := context.WithTimeout(context.Background(), persistenceOperationTimeout)
93 > defer cancel()
94 >
95 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
96 > currentClusterMetadata, err := factory.MetadataManager.GetCurrentClusterMetadata(ctx)
97 > if err != nil {
98 factory.Logger.Fatal("Failed to get current cluster ID", tag.Error(err))
99 }
100
101 > appName := "temporal" factory.go
102 > if currentClusterMetadata.UseClusterIdMembership {
103 > appName = fmt.Sprintf("temporal-%s", currentClusterMetadata.GetClusterId())
104 > }
105 > rp, err := ringpop.New(appName, ringpop.Channel(factory.getTChannel()), ringpop.AddressResolverFunc(factory.broadcastAddressResolver))
106 > if err != nil {
107 factory.Logger.Fatal("Failed to get new ringpop", tag.Error(err))
108 }
110 // Empirically, ringpop updates usually propagate in under a second even in relatively large clusters.
111 // 3 seconds is an over-estimate to be safer.
112 > maxPropagationTime := dynamicconfig.RingpopApproximateMaxPropagationTime.Get(factory.DC)() factory.go
113 > replicaPoints := dynamicconfig.RingpopReplicaPoints.Get(factory.DC)()
114 >
115 > factory.monitor = newMonitor(
116 > factory.ServiceName,
117 > factory.ServicePortMap,
118 > rp,
119 > factory.Logger,
120 > factory.MetadataManager,
121 > factory.broadcastAddressResolver,
122 > factory.Config.MaxJoinDuration,
123 > maxPropagationTime,
124 > factory.getJoinTime(maxPropagationTime),
125 > replicaPoints,
126 > )
127 })
128
129 > return factory.monitor factory.go
130 }
131
132 > func (factory *factory) getJoinTime(maxPropagationTime time.Duration) time.Time { factory.go
133 > var alignTime time.Duration
134 > switch factory.ServiceName {
135 > case primitives.MatchingService:
136 > alignTime = dynamicconfig.MatchingAlignMembershipChange.Get(factory.DC)()
137 > case primitives.HistoryService:
138 > alignTime = dynamicconfig.HistoryAlignMembershipChange.Get(factory.DC)()
139 }
140 > if alignTime == 0 { factory.go
141 > return time.Time{}
142 > }
143 return util.NextAlignedTime(time.Now().Add(maxPropagationTime), alignTime)
144 }
145
146 > func (factory *factory) broadcastAddressResolver() (string, error) { factory.go
147 > return buildBroadcastHostPort(factory.getTChannel().PeerInfo(), factory.Config.BroadcastAddress)
148 > }
149
150 > func (factory *factory) getTChannel() *tchannel.Channel { factory.go
151 > factory.chOnce.Do(func() {
152 > ringpopServiceName := fmt.Sprintf("%v-ringpop", factory.ServiceName)
153 > ringpopHostAddress := net.JoinHostPort(factory.getListenIP().String(), convert.IntToString(factory.RPCConfig.MembershipPort))
154 > enableTLS := dynamicconfig.EnableRingpopTLS.Get(factory.DC)()
155 >
156 > var tChannel *tchannel.Channel
157 > if enableTLS {
158 tChannel = factory.getTLSChannel(ringpopHostAddress, ringpopServiceName)
159 > } else { factory.go
160 > tChannel = factory.getTCPChannel(ringpopHostAddress, ringpopServiceName) factory.go
161 > }
162 > factory.channel = tChannel factory.go
163 })
164
165 > return factory.channel factory.go
166 }
167
168 > func (factory *factory) getTCPChannel(ringpopHostAddress string, ringpopServiceName string) *tchannel.Channel { factory.go
169 > listener, err := net.Listen("tcp", ringpopHostAddress)
170 > if err != nil {
171 factory.Logger.Fatal("Failed to start ringpop listener", tag.Error(err), tag.Address(ringpopHostAddress))
172 }
173
174 > tChannel, err := tchannel.NewChannel(ringpopServiceName, &tchannel.ChannelOptions{}) factory.go
175 > if err != nil {
176 factory.Logger.Fatal("Failed to create ringpop TChannel", tag.Error(err))
177 }
178
179 > if err := tChannel.Serve(listener); err != nil { factory.go
180 factory.Logger.Fatal("Failed to serve ringpop listener", tag.Error(err), tag.Address(ringpopHostAddress))
181 }
182 > return tChannel factory.go
183 }
184
211 }
212
213 > func (factory *factory) getListenIP() net.IP { factory.go
214 > if factory.RPCConfig.BindOnLocalHost && len(factory.RPCConfig.BindOnIP) > 0 {
215 factory.Logger.Fatal("ListenIP failed, bindOnLocalHost and bindOnIP are mutually exclusive")
216 return nil
217 }
218
219 > if factory.RPCConfig.BindOnLocalHost { factory.go
220 > return net.ParseIP(environment.GetLocalhostIP()) factory.go
221 > }
222
223 > if len(factory.RPCConfig.BindOnIP) > 0 { factory.go
224 > ip := net.ParseIP(factory.RPCConfig.BindOnIP)
225 > if ip != nil {
226 > return ip
227 > }
228
229 factory.Logger.Fatal("ListenIP failed, unable to parse bindOnIP value", tag.Address(factory.RPCConfig.BindOnIP))
240
241 // closeTChannel allows fx Stop hook to close channel
242 > func (factory *factory) closeTChannel() { factory.go
243 > if factory.channel != nil {
244 > factory.getTChannel().Close()
245 > factory.channel = nil
246 > }
247 }
248
249 > func (factory *factory) getHostInfoProvider() (membership.HostInfoProvider, error) { factory.go
250 > address, err := factory.broadcastAddressResolver()
251 > if err != nil {
252 return nil, err
253 }
254
255 > servicePort, ok := factory.ServicePortMap[factory.ServiceName] factory.go
256 > if !ok {
257 return nil, membership.ErrUnknownService
258 }
261 // ringpop messages. We use a different port for the service, so we
262 // replace that portion.
263 > serviceAddress, err := replaceServicePort(address, servicePort) factory.go
264 > if err != nil {
265 return nil, err
266 }
267
268 > hostInfo := membership.NewHostInfoFromAddress(serviceAddress) factory.go
269 > return membership.NewHostInfoProvider(hostInfo), nil
270 }
go.temporal.io/server/service/worker/scanner/scanner.go 98 covered LOC · 20 ranges

Open complete file

131 hostInfo membership.HostInfo,
132 serializer serialization.Serializer,
133 > ) *Scanner { scanner.go
134 > return &Scanner{
135 > context: scannerContext{
136 > cfg: cfg,
137 > sdkClientFactory: sdkClientFactory,
138 > logger: logger,
139 > metricsHandler: metricsHandler,
140 > executionManager: executionManager,
141 > taskManager: taskManager,
142 > visibilityManager: visibilityManager,
143 > metadataManager: metadataManager,
144 > historyClient: historyClient,
145 > matchingClient: matchingClient,
146 > adminClient: adminClient,
147 > namespaceRegistry: registry,
148 > currentClusterName: currentClusterName,
149 > hostInfo: hostInfo,
150 > serializer: serializer,
151 > },
152 > }
153 > }
154
155 // Start starts the scanner
156 > func (s *Scanner) Start() error { scanner.go
157 > ctx := context.WithValue(context.Background(), scannerContextKey, s.context)
158 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
159 > ctx, s.lifecycleCancel = context.WithCancel(ctx)
160 >
161 > workerOpts := worker.Options{
162 > Identity: "temporal-system@" + s.context.hostInfo.Identity(),
163 > MaxConcurrentActivityExecutionSize: s.context.cfg.MaxConcurrentActivityExecutionSize(),
164 > MaxConcurrentWorkflowTaskExecutionSize: s.context.cfg.MaxConcurrentWorkflowTaskExecutionSize(),
165 > MaxConcurrentActivityTaskPollers: s.context.cfg.MaxConcurrentActivityTaskPollers(),
166 > MaxConcurrentWorkflowTaskPollers: s.context.cfg.MaxConcurrentWorkflowTaskPollers(),
167 >
168 > BackgroundActivityContext: ctx,
169 > }
170 >
171 > var workerTaskQueueNames []string
172 > if s.context.cfg.Persistence.DefaultStoreType() != config.StoreTypeSQL && s.context.cfg.ExecutionsScannerEnabled() {
173 s.wg.Add(1)
174 go s.startWorkflowWithRetry(ctx, executionsScannerWFStartOptions, executionsScannerWFTypeName)
175 workerTaskQueueNames = append(workerTaskQueueNames, executionsScannerTaskQueueName)
176 > } else if s.context.cfg.ExecutionsScannerEnabled() { scanner.go
177 s.context.logger.Info("ExecutionsScanner is not supported for SQL store")
178 }
179
180 > if s.context.cfg.Persistence.DefaultStoreType() == config.StoreTypeSQL && s.context.cfg.TaskQueueScannerEnabled() { scanner.go
181 > s.wg.Add(1) scanner.go
182 > go s.startWorkflowWithRetry(ctx, tlScannerWFStartOptions, tqScannerWFTypeName)
183 > workerTaskQueueNames = append(workerTaskQueueNames, tqScannerTaskQueueName)
184 > }
185
186 > if s.context.cfg.HistoryScannerEnabled() { scanner.go
187 > s.wg.Add(1) scanner.go
188 > go s.startWorkflowWithRetry(ctx, historyScannerWFStartOptions, historyScannerWFTypeName)
189 > workerTaskQueueNames = append(workerTaskQueueNames, historyScannerTaskQueueName)
190 > }
191
192 > if s.context.cfg.BuildIdScavengerEnabled() { scanner.go
193 s.wg.Add(1)
194 go s.startWorkflowWithRetry(ctx, build_ids.BuildIdScavengerWFStartOptions, build_ids.BuildIdScavangerWorkflowName)
216 }
217
218 > siOpts := s.context.cfg.ScheduleInvariantsScannerOptions() scanner.go
219 > if siOpts.OverdueNextActionTimeEnabled || siOpts.StuckOpenEnabled || siOpts.UnknownStateEnabled {
220 scheduleActivities := scheduleinvariants.NewActivities(
221 s.context.logger,
271
272 // TODO: There's no reason to register all activities and workflows on every task queue.
273 > for _, tl := range workerTaskQueueNames { scanner.go
274 > work := s.context.sdkClientFactory.NewWorker(s.context.sdkClientFactory.GetSystemClient(), tl, workerOpts) scanner.go
275 >
276 > work.RegisterWorkflowWithOptions(TaskQueueScannerWorkflow, workflow.RegisterOptions{Name: tqScannerWFTypeName})
277 > work.RegisterWorkflowWithOptions(HistoryScannerWorkflow, workflow.RegisterOptions{Name: historyScannerWFTypeName})
278 > work.RegisterWorkflowWithOptions(ExecutionsScannerWorkflow, workflow.RegisterOptions{Name: executionsScannerWFTypeName})
279 > work.RegisterActivityWithOptions(TaskQueueScavengerActivity, activity.RegisterOptions{Name: taskQueueScavengerActivityName})
280 > work.RegisterActivityWithOptions(HistoryScavengerActivity, activity.RegisterOptions{Name: historyScavengerActivityName})
281 > work.RegisterActivityWithOptions(ExecutionsScavengerActivity, activity.RegisterOptions{Name: executionsScavengerActivityName})
282 >
283 > // TODO: Nothing is gracefully stopping these workers or listening for fatal errors.
284 > if err := work.Start(); err != nil {
285 > return err scanner.go
286 > }
287 }
288
290 }
291
292 > func (s *Scanner) Stop() { scanner.go
293 > s.lifecycleCancel()
294 > s.wg.Wait()
295 > }
296
297 // startWorkflowWithRetry starts a scanner workflow, retrying until it succeeds or the
298 // scanner shuts down. workflowType may be either a registered type-name string or the
299 // workflow function itself (registered under its Go function name).
300 > func (s *Scanner) startWorkflowWithRetry(ctx context.Context, options sdkclient.StartWorkflowOptions, workflowType string, workflowArgs ...any) { scanner.go
301 > defer s.wg.Done()
302 >
303 > policy := backoff.NewExponentialRetryPolicy(time.Second).
304 > WithMaximumInterval(time.Minute).
305 > WithExpirationInterval(backoff.NoInterval)
306 > err := backoff.ThrottleRetryContext(ctx, func(ctx context.Context) error {
307 > return s.startWorkflow(
308 > ctx,
309 > s.context.sdkClientFactory.GetSystemClient(),
310 > options,
311 > workflowType,
312 > workflowArgs...,
313 > )
314 > }, policy, func(err error) bool {
315 > return true scanner.go
316 > })
317 // if the scanner shuts down before the workflow is started, then the error will be context canceled
318 > if err != nil && !common.IsContextCanceledErr(err) { scanner.go
319 > s.context.logger.Fatal("unable to start scanner", tag.WorkflowType(workflowType), tag.Error(err)) scanner.go
320 > }
321 }
322
327 workflowType string,
328 workflowArgs ...any,
329 > ) error { scanner.go
330 > ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
331 > _, err := client.ExecuteWorkflow(ctx, options, workflowType, workflowArgs...)
332 > cancel()
333 > if err != nil {
334 > if _, ok := err.(*serviceerror.WorkflowExecutionAlreadyStarted); ok { scanner.go
335 return nil
336 }
337 > s.context.logger.Error("error starting workflow", tag.WorkflowType(workflowType), tag.Error(err)) scanner.go
338 > return err
339 }
340 s.context.logger.Info("workflow successfully started", tag.WorkflowType(workflowType))
go.temporal.io/server/common/authorization/interceptor.go 97 covered LOC · 31 ranges

Open complete file

56
57 // TLSInfoFromContext extracts TLS information from the context's peer value.
58 > func TLSInfoFromContext(ctx context.Context) *credentials.TLSInfo { interceptor.go
59 > p, ok := peer.FromContext(ctx)
60 > if !ok {
61 return nil
62 }
63 > if tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo); ok { interceptor.go
64 return &tlsInfo
65 }
66 > return nil interceptor.go
67 }
68
69 // PeerCert extracts an x509 certificate from given tlsInfo.
70 > func PeerCert(tlsInfo *credentials.TLSInfo) *x509.Certificate { interceptor.go
71 > if tlsInfo == nil || len(tlsInfo.State.VerifiedChains) == 0 || len(tlsInfo.State.VerifiedChains[0]) == 0 {
72 > return nil interceptor.go
73 > }
74 // The assumption here is that we only expect a single verified chain of certs (first[0]).
75 // It's unclear how we should handle a situation when more than one chain is presented,
110 enablePrincipalPropagation dynamicconfig.BoolPropertyFnWithNamespaceFilter,
111 disableStreamingAuthorizer dynamicconfig.BoolPropertyFn,
112 > ) *Interceptor { interceptor.go
113 > return &Interceptor{
114 > claimMapper: claimMapper,
115 > authorizer: authorizer,
116 > logger: logger,
117 > namespaceChecker: namespaceChecker,
118 > metricsHandler: metricsHandler,
119 > authHeaderName: cmp.Or(authHeaderName, defaultAuthHeaderName),
120 > authExtraHeaderName: cmp.Or(authExtraHeaderName, defaultAuthExtraHeaderName),
121 > audienceGetter: audienceGetter,
122 > exposeAuthorizerErrors: exposeAuthorizerErrors,
123 > enableCrossNamespaceCommands: enableCrossNamespaceCommands,
124 > enablePrincipalPropagation: enablePrincipalPropagation,
125 > disableStreamingAuthorizer: disableStreamingAuthorizer,
126 > }
127 > }
128
129 func (a *Interceptor) Intercept(
132 info *grpc.UnaryServerInfo,
133 handler grpc.UnaryHandler,
134 > ) (any, error) { interceptor.go
135 > tlsConnection := TLSInfoFromContext(ctx)
136 >
137 > authInfo := a.GetAuthInfo(tlsConnection, headers.NewGRPCHeaderGetter(ctx), func() string {
138 if a.audienceGetter != nil {
139 return a.audienceGetter.Audience(ctx, req, info)
142 })
143
144 > var claims *Claims interceptor.go
145 > if authInfo != nil {
146 var err error
147 claims, err = a.GetClaims(authInfo)
156 // Always strip inbound principal headers to prevent external callers from
157 // spoofing principal identity, regardless of whether the authorizer is enabled.
158 > ctx = headers.StripPrincipal(ctx) interceptor.go
159 >
160 > if a.authorizer != nil {
161 > var namespace string interceptor.go
162 > requestWithNamespace, ok := req.(hasNamespace)
163 > if ok {
164 > namespace = requestWithNamespace.GetNamespace()
165 > }
166 > ct := &CallTarget{
167 > Namespace: namespace,
168 > APIName: info.FullMethod,
169 > Request: req,
170 > }
171 > principal, err := a.Authorize(ctx, claims, ct)
172 > if err != nil {
173 > return nil, err interceptor.go
174 > }
175 > if a.enablePrincipalPropagation != nil && a.enablePrincipalPropagation(namespace) && principal != nil { interceptor.go
176 ctx = headers.SetPrincipal(ctx, principal)
177 }
178
179 // Authorize target namespaces in cross-namespace commands
180 > if err := a.authorizeTargetNamespaces(ctx, claims, namespace, req); err != nil { interceptor.go
181 return nil, err
182 }
183 }
184 > return handler(ctx, req) interceptor.go
185 }
186
249 // Returns nil if either the policy's claimMapper or authorizer are nil or when there is no auth information in the
250 // provided TLS info or headers.
251 > func (a *Interceptor) GetAuthInfo(tlsConnection *credentials.TLSInfo, header headers.HeaderGetter, audienceGetter func() string) *AuthInfo { interceptor.go
252 > if a.claimMapper == nil || a.authorizer == nil {
253 return nil
254 }
255 > var tlsSubject *pkix.Name interceptor.go
256 > var authHeader string
257 > var authExtraHeader string
258 >
259 > if header != nil {
260 > authHeader = header.Get(a.authHeaderName)
261 > authExtraHeader = header.Get(a.authExtraHeaderName)
262 > }
263 > clientCert := PeerCert(tlsConnection)
264 > if clientCert != nil {
265 tlsSubject = &clientCert.Subject
266 }
267
268 > authInfoRequired := true interceptor.go
269 > if cm, ok := a.claimMapper.(ClaimMapperWithAuthInfoRequired); ok {
270 authInfoRequired = cm.AuthInfoRequired()
271 }
272
273 // Add auth info to context only if there's some auth info
274 > if tlsSubject == nil && authHeader == "" && authInfoRequired { interceptor.go
275 > return nil interceptor.go
276 > }
277
278 return &AuthInfo{
302 // Logs and emits metrics when unauthorized.
303 // Returns the principal identity and any authorization error.
304 > func (a *Interceptor) Authorize(ctx context.Context, claims *Claims, ct *CallTarget) (*commonpb.Principal, error) { interceptor.go
305 > if a.authorizer == nil {
306 return nil, nil
307 }
308
309 > mh := a.getMetricsHandler(ct.Namespace) interceptor.go
310 >
311 > startTime := time.Now().UTC()
312 > result, err := a.authorizer.Authorize(ctx, claims, ct)
313 > metrics.ServiceAuthorizationLatency.With(mh).Record(time.Since(startTime))
314 > if err != nil {
315 metrics.ServiceErrAuthorizeFailedCounter.With(mh).Record(1)
316 a.logger.Error("Authorization error", tag.Error(err))
320 return nil, errUnauthorized // return a generic error to the caller without disclosing details
321 }
322 > if result.Decision != DecisionAllow { interceptor.go
323 > metrics.ServiceErrUnauthorizedCounter.With(mh).Record(1) interceptor.go
324 > // if a reason is included in the result, include it in the error message
325 > if result.Reason != "" {
326 return nil, serviceerror.NewPermissionDenied(RequestUnauthorized, result.Reason)
327 }
328 > return nil, errUnauthorized // return a generic error to the caller without disclosing details interceptor.go
329 }
330 > return result.Principal, nil interceptor.go
331 }
332
333 // getMetricsHandler returns a metrics handler with a namespace tag
334 > func (a *Interceptor) getMetricsHandler(nsName string) metrics.Handler { interceptor.go
335 > nsTag := metrics.NamespaceUnknownTag()
336 > if nsName != "" {
337 > // Note that this is before the namespace state validation interceptor, so this interceptor.go
338 > // namespace name is not validated. We should only use it as a metric tag if it's a
339 > // real namespace, to avoid unbounded cardinality issues.
340 > if a.namespaceChecker.Exists(namespace.Name(nsName)) == nil {
341 > nsTag = metrics.NamespaceTag(nsName) interceptor.go
342 > }
343 }
344 > return a.metricsHandler.WithTags(metrics.OperationTag(metrics.AuthorizationScope), nsTag) interceptor.go
345 }
346
354 sourceNamespace string,
355 req any,
356 > ) error { interceptor.go
357 > // Skip if cross-namespace commands are not enabled
358 > if !a.enableCrossNamespaceCommands() {
359 > return nil interceptor.go
360 > }
361
362 // Cross-namespace commands can only be initiated via RespondWorkflowTaskCompletedRequest.
go.temporal.io/server/temporal/server_impl.go 97 covered LOC · 13 ranges

Open complete file

65 metricsHandler metrics.Handler,
66 serializer serialization.Serializer,
67 > ) *ServerImpl { server_impl.go
68 > s := &ServerImpl{
69 > so: opts,
70 > stoppedCh: stoppedCh,
71 > logger: logger,
72 > namespaceLogger: namespaceLogger,
73 > persistenceConfig: persistenceConfig,
74 > clusterMetadata: clusterMetadata,
75 > persistenceFactoryProvider: persistenceFactoryProvider,
76 > metricsHandler: metricsHandler,
77 > }
78 > for _, svcMeta := range servicesGroup.Services {
79 > if svcMeta != nil {
80 > s.servicesMetadata = append(s.servicesMetadata, svcMeta)
81 > }
82 }
83 // Store serializer for use in Start()
84 > s.serializer = serializer server_impl.go
85 > return s
86 }
87
88 > func (s *ServerImpl) Start(ctx context.Context) error { server_impl.go
89 > s.logger.Info("Starting server for services", tag.Value(s.so.serviceNames))
90 > s.logger.Debug(s.so.config.String())
91 >
92 > if err := initSystemNamespaces(
93 > ctx,
94 > &s.persistenceConfig,
95 > s.clusterMetadata.CurrentClusterName,
96 > s.so.persistenceServiceResolver,
97 > s.persistenceFactoryProvider,
98 > s.logger,
99 > s.so.customDataStoreFactory,
100 > s.metricsHandler,
101 > s.serializer,
102 > ); err != nil {
103 return fmt.Errorf("unable to initialize system namespace: %w", err)
104 }
105
106 > return s.startServices() server_impl.go
107 }
108
109 > func (s *ServerImpl) Stop(ctx context.Context) error { server_impl.go
110 > close(s.stoppedCh)
111 >
112 > svcs := slices.Clone(s.servicesMetadata)
113 > slices.SortFunc(svcs, func(a, b *ServicesMetadata) int {
114 > return -cmp.Compare(initOrder[a.serviceName], initOrder[b.serviceName]) // note negative
115 > })
116 > for _, svc := range svcs {
117 > svc.Stop(ctx)
118 > }
119
120 > if s.so.metricHandler != nil { server_impl.go
121 s.so.metricHandler.Stop(s.logger)
122 }
123 > return nil server_impl.go
124 }
125
126 > func (s *ServerImpl) startServices() error { server_impl.go
127 > // The membership join time may exceed the configured max join duration.
128 > // Double the service start timeout to make sure there is enough time for start logic.
129 > timeout := max(serviceStartTimeout, 2*s.so.config.Global.Membership.MaxJoinDuration)
130 > ctx, cancel := context.WithTimeout(context.Background(), timeout)
131 > defer cancel()
132 >
133 > svcs := slices.Clone(s.servicesMetadata)
134 > slices.SortFunc(svcs, func(a, b *ServicesMetadata) int {
135 > return cmp.Compare(initOrder[a.serviceName], initOrder[b.serviceName])
136 > })
137
138 > var allErrs error server_impl.go
139 > for _, svc := range svcs {
140 > err := svc.app.Start(ctx)
141 > if err != nil {
142 allErrs = multierr.Append(allErrs, fmt.Errorf("failed to start service %v: %w", svc.serviceName, err))
143 }
144 }
145 > return allErrs server_impl.go
146 }
147
156 metricsHandler metrics.Handler,
157 serializer serialization.Serializer,
158 > ) error { server_impl.go
159 > clusterName := persistenceClient.ClusterName(currentClusterName)
160 > metricsHandler = metricsHandler.WithTags(metrics.ServiceNameTag(primitives.ServerService))
161 > dataStoreFactory := persistenceClient.DataStoreFactoryProvider(
162 > clusterName,
163 > persistenceServiceResolver,
164 > cfg,
165 > customDataStoreFactory,
166 > logger,
167 > metricsHandler,
168 > telemetry.NoopTracerProvider,
169 > serializer,
170 > )
171 > factory := persistenceFactoryProvider(persistenceClient.NewFactoryParams{
172 > DataStoreFactory: dataStoreFactory,
173 > Cfg: cfg,
174 > PersistenceMaxQPS: nil,
175 > PersistenceNamespaceMaxQPS: nil,
176 > ClusterName: persistenceClient.ClusterName(currentClusterName),
177 > MetricsHandler: metricsHandler,
178 > Logger: logger,
179 > Serializer: serializer,
180 > })
181 > defer factory.Close()
182 >
183 > metadataManager, err := factory.NewMetadataManager()
184 > if err != nil {
185 return fmt.Errorf("unable to initialize metadata manager: %w", err)
186 }
187 > defer metadataManager.Close() server_impl.go
188 > ctx, cancel := context.WithTimeout(
189 > headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo),
190 > 30*time.Second,
191 > )
192 > defer cancel()
193 >
194 > if err = metadataManager.InitializeSystemNamespaces(ctx, currentClusterName); err != nil {
195 return fmt.Errorf("unable to register system namespace: %w", err)
196 }
197 > return nil server_impl.go
198 }
go.temporal.io/server/common/persistence/metadata_manager.go 95 covered LOC · 22 ranges

Open complete file

37 logger log.Logger,
38 clusterName string,
39 > ) MetadataManager { metadata_manager.go
40 > return &metadataManagerImpl{
41 > serializer: serializer,
42 > persistence: persistence,
43 > logger: logger,
44 > clusterName: clusterName,
45 > }
46 > }
47
48 func (m *metadataManagerImpl) GetName() string {
53 ctx context.Context,
54 request *CreateNamespaceRequest,
55 > ) (*CreateNamespaceResponse, error) { metadata_manager.go
56 > datablob, err := m.serializer.NamespaceDetailToBlob(request.Namespace)
57 > if err != nil {
58 return nil, err
59 }
60
61 > return m.persistence.CreateNamespace(ctx, &InternalCreateNamespaceRequest{ metadata_manager.go
62 > ID: request.Namespace.Info.Id,
63 > Name: request.Namespace.Info.Name,
64 > IsGlobal: request.IsGlobalNamespace,
65 > Namespace: datablob,
66 > })
67 }
68
70 ctx context.Context,
71 request *GetNamespaceRequest,
72 > ) (*GetNamespaceResponse, error) { metadata_manager.go
73 > resp, err := m.persistence.GetNamespace(ctx, request)
74 > if err != nil {
75 return nil, err
76 }
77 > return ConvertInternalGetNamespaceResponse(m.serializer, m.clusterName, resp) metadata_manager.go
78 }
79
148 }
149
150 > func ConvertInternalGetNamespaceResponse(serializer serialization.Serializer, currentClusterName string, d *InternalGetNamespaceResponse) (*GetNamespaceResponse, error) { metadata_manager.go
151 > ns, err := serializer.NamespaceDetailFromBlob(d.Namespace)
152 > if err != nil {
153 return nil, err
154 }
155
156 > if ns.Info.Data == nil { metadata_manager.go
157 > ns.Info.Data = map[string]string{} metadata_manager.go
158 > }
159
160 > if ns.Config.BadBinaries == nil || ns.Config.BadBinaries.Binaries == nil { metadata_manager.go
161 > ns.Config.BadBinaries = &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}} metadata_manager.go
162 > }
163
164 > ns.ReplicationConfig.ActiveClusterName = GetOrUseDefaultActiveCluster(currentClusterName, ns.ReplicationConfig.ActiveClusterName) metadata_manager.go
165 > ns.ReplicationConfig.Clusters = GetOrUseDefaultClusters(currentClusterName, ns.ReplicationConfig.Clusters)
166 > return &GetNamespaceResponse{
167 > Namespace: ns,
168 > IsGlobalNamespace: d.IsGlobal,
169 > NotificationVersion: d.NotificationVersion,
170 > }, nil
171 }
172
174 ctx context.Context,
175 request *ListNamespacesRequest,
176 > ) (*ListNamespacesResponse, error) { metadata_manager.go
177 > var namespaces []*GetNamespaceResponse
178 > nextPageToken := request.NextPageToken
179 > pageSize := request.PageSize
180 >
181 > for {
182 > resp, err := m.persistence.ListNamespaces(ctx, &InternalListNamespacesRequest{
183 > PageSize: pageSize,
184 > NextPageToken: nextPageToken,
185 > })
186 > if err != nil {
187 return nil, err
188 }
189 > deletedNamespacesCount := 0 metadata_manager.go
190 > for _, d := range resp.Namespaces {
191 > ret, err := ConvertInternalGetNamespaceResponse(m.serializer, m.clusterName, d) metadata_manager.go
192 > if err != nil {
193 return nil, err
194 }
195 > if ret.Namespace.Info.State == enumspb.NAMESPACE_STATE_DELETED && !request.IncludeDeleted { metadata_manager.go
196 deletedNamespacesCount++
197 continue
198 }
199 > namespaces = append(namespaces, ret) metadata_manager.go
200 }
201 > nextPageToken = resp.NextPageToken metadata_manager.go
202 > if len(nextPageToken) == 0 {
203 > // Page wasn't full, no more namespaces in DB.
204 > break
205 }
206 if deletedNamespacesCount == 0 {
211 }
212
213 > return &ListNamespacesResponse{ metadata_manager.go
214 > Namespaces: namespaces,
215 > NextPageToken: nextPageToken,
216 > }, nil
217 }
218
220 ctx context.Context,
221 currentClusterName string,
222 > ) error { metadata_manager.go
223 > _, err := m.CreateNamespace(ctx, &CreateNamespaceRequest{
224 > Namespace: &persistencespb.NamespaceDetail{
225 > Info: &persistencespb.NamespaceInfo{
226 > Id: primitives.SystemNamespaceID,
227 > Name: primitives.SystemLocalNamespace,
228 > State: enumspb.NAMESPACE_STATE_REGISTERED,
229 > Description: "Temporal internal system namespace",
230 > Owner: "[email protected]",
231 > },
232 > Config: &persistencespb.NamespaceConfig{
233 > Retention: durationpb.New(primitives.SystemNamespaceRetention),
234 > HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
235 > VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
236 > },
237 > ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
238 > ActiveClusterName: currentClusterName,
239 > Clusters: []string{currentClusterName},
240 > },
241 > FailoverVersion: common.EmptyVersion,
242 > FailoverNotificationVersion: -1,
243 > },
244 > IsGlobalNamespace: false,
245 > })
246 >
247 > if err != nil {
248 if _, ok := err.(*serviceerror.NamespaceAlreadyExists); !ok {
249 return err
250 }
251 }
252 > return nil metadata_manager.go
253 }
254
259 }
260
261 > func (m *metadataManagerImpl) Close() { metadata_manager.go
262 > m.persistence.Close()
263 > }
264
265 > func (m *metadataManagerImpl) WatchNamespaces(context.Context) (<-chan *NamespaceWatchEvent, error) { metadata_manager.go
266 > return nil, ErrWatchNotSupported
267 > }
go.temporal.io/server/api/persistence/v1/executions.pb.go 94 covered LOC · 9 ranges

Open complete file

53 }
54
55 > func (x *ShardInfo) Reset() { executions.pb.go
56 > *x = ShardInfo{}
57 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[0]
58 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
59 > ms.StoreMessageInfo(mi)
60 > }
61
62 func (x *ShardInfo) String() string {
66 func (*ShardInfo) ProtoMessage() {}
67
68 > func (x *ShardInfo) ProtoReflect() protoreflect.Message { executions.pb.go
69 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[0]
70 > if x != nil {
71 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
72 > if ms.LoadMessageInfo() == nil {
73 > ms.StoreMessageInfo(mi)
74 > }
75 > return ms
76 }
77 return mi.MessageOf(x)
83 }
84
85 > func (x *ShardInfo) GetShardId() int32 { executions.pb.go
86 > if x != nil {
87 > return x.ShardId
88 > }
89 return 0
90 }
91
92 > func (x *ShardInfo) GetRangeId() int64 { executions.pb.go
93 > if x != nil {
94 > return x.RangeId
95 > }
96 return 0
97 }
98
99 > func (x *ShardInfo) GetOwner() string { executions.pb.go
100 > if x != nil {
101 > return x.Owner
102 > }
103 return ""
104 }
118 }
119
120 > func (x *ShardInfo) GetReplicationDlqAckLevel() map[string]int64 { executions.pb.go
121 > if x != nil {
122 > return x.ReplicationDlqAckLevel
123 > }
124 return nil
125 }
126
127 > func (x *ShardInfo) GetQueueStates() map[int32]*QueueState { executions.pb.go
128 > if x != nil {
129 > return x.QueueStates
130 > }
131 return nil
132 }
5706 }
5707
5708 > func init() { file_temporal_server_api_persistence_v1_executions_proto_init() } executions.pb.go
5709 > func file_temporal_server_api_persistence_v1_executions_proto_init() {
5710 > if File_temporal_server_api_persistence_v1_executions_proto != nil {
5711 > return
5712 > }
5713 > file_temporal_server_api_persistence_v1_chasm_proto_init()
5714 > file_temporal_server_api_persistence_v1_hsm_proto_init()
5715 > file_temporal_server_api_persistence_v1_queues_proto_init()
5716 > file_temporal_server_api_persistence_v1_update_proto_init()
5717 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[1].OneofWrappers = []any{
5718 > (*WorkflowExecutionInfo_LastWorkflowTaskFailureCause)(nil),
5719 > (*WorkflowExecutionInfo_LastWorkflowTaskTimedOutType)(nil),
5720 > }
5721 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[8].OneofWrappers = []any{
5722 > (*TransferTaskInfo_CloseExecutionTaskDetails_)(nil),
5723 > (*TransferTaskInfo_ChasmTaskInfo)(nil),
5724 > }
5725 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[10].OneofWrappers = []any{
5726 > (*VisibilityTaskInfo_ChasmTaskInfo)(nil),
5727 > }
5728 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[11].OneofWrappers = []any{
5729 > (*TimerTaskInfo_ChasmTaskInfo)(nil),
5730 > }
5731 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[13].OneofWrappers = []any{
5732 > (*OutboundTaskInfo_StateMachineInfo)(nil),
5733 > (*OutboundTaskInfo_ChasmTaskInfo)(nil),
5734 > (*OutboundTaskInfo_WorkerCommandsTask)(nil),
5735 > }
5736 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[17].OneofWrappers = []any{
5737 > (*ActivityInfo_UseWorkflowBuildIdInfo_)(nil),
5738 > (*ActivityInfo_LastIndependentlyAssignedBuildId)(nil),
5739 > }
5740 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[23].OneofWrappers = []any{
5741 > (*Callback_Nexus_)(nil),
5742 > (*Callback_Hsm)(nil),
5743 > }
5744 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[40].OneofWrappers = []any{
5745 > (*ActivityInfo_PauseInfo_Manual_)(nil),
5746 > (*ActivityInfo_PauseInfo_RuleId)(nil),
5747 > }
5748 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[46].OneofWrappers = []any{
5749 > (*CallbackInfo_Trigger_WorkflowClosed)(nil),
5750 > }
5751 > type x struct{}
5752 > out := protoimpl.TypeBuilder{
5753 > File: protoimpl.DescBuilder{
5754 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
5755 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_executions_proto_rawDesc), len(file_temporal_server_api_persistence_v1_executions_proto_rawDesc)),
5756 > NumEnums: 0,
5757 > NumMessages: 47,
5758 > NumExtensions: 0,
5759 > NumServices: 0,
5760 > },
5761 > GoTypes: file_temporal_server_api_persistence_v1_executions_proto_goTypes,
5762 > DependencyIndexes: file_temporal_server_api_persistence_v1_executions_proto_depIdxs,
5763 > MessageInfos: file_temporal_server_api_persistence_v1_executions_proto_msgTypes,
5764 > }.Build()
5765 > File_temporal_server_api_persistence_v1_executions_proto = out.File
5766 > file_temporal_server_api_persistence_v1_executions_proto_goTypes = nil
5767 > file_temporal_server_api_persistence_v1_executions_proto_depIdxs = nil
5768 }
go.temporal.io/server/common/persistence/client/fx.go 93 covered LOC · 16 ranges

Open complete file

85 )
86
87 > func ClusterNameProvider(config *cluster.Config) ClusterName { fx.go
88 > return ClusterName(config.CurrentClusterName)
89 > }
90
91 func EventBlobCacheProvider(
93 logger log.Logger,
94 serializer serialization.Serializer,
95 > ) persistence.XDCCache { fx.go
96 > return persistence.NewEventsBlobCache(
97 > dynamicconfig.XDCCacheMaxSizeBytes.Get(dc)(),
98 > 20*time.Second,
99 > logger,
100 > )
101 > }
102
103 func EnableDataLossMetricsProvider(
104 dc *dynamicconfig.Collection,
105 > ) EnableDataLossMetrics { fx.go
106 > return EnableDataLossMetrics(dynamicconfig.EnableDataLossMetrics.Get(dc))
107 > }
108
109 func EnableBestEffortDeleteTasksOnWorkflowUpdateProvider(
110 dc *dynamicconfig.Collection,
111 > ) EnableBestEffortDeleteTasksOnWorkflowUpdate { fx.go
112 > return EnableBestEffortDeleteTasksOnWorkflowUpdate(dynamicconfig.EnableBestEffortDeleteTasksOnWorkflowUpdate.Get(dc))
113 > }
114
115 func FactoryProvider(
116 params NewFactoryParams,
117 > ) Factory { fx.go
118 > var systemRequestRateLimiter, namespaceRequestRateLimiter, shardRequestRateLimiter quotas.RequestRateLimiter
119 > if params.PersistenceMaxQPS != nil && params.PersistenceMaxQPS() > 0 {
120 > systemRequestRateLimiter = NewPriorityRateLimiter(
121 > params.PersistenceMaxQPS,
122 > RequestPriorityFn,
123 > params.OperatorRPSRatio,
124 > params.PersistenceBurstRatio,
125 > params.HealthSignals,
126 > params.DynamicRateLimitingParams,
127 > params.MetricsHandler,
128 > params.Logger,
129 > )
130 > namespaceRequestRateLimiter = NewPriorityNamespaceRateLimiter(
131 > params.PersistenceMaxQPS,
132 > params.PersistenceNamespaceMaxQPS,
133 > RequestPriorityFn,
134 > params.OperatorRPSRatio,
135 > params.PersistenceBurstRatio,
136 > )
137 > shardRequestRateLimiter = NewPriorityNamespaceShardRateLimiter(
138 > params.PersistenceMaxQPS,
139 > params.PersistencePerShardNamespaceMaxQPS,
140 > RequestPriorityFn,
141 > params.OperatorRPSRatio,
142 > params.PersistenceBurstRatio,
143 > )
144 > }
145
146 > return NewFactory( fx.go
147 > params.DataStoreFactory,
148 > params.Cfg,
149 > systemRequestRateLimiter,
150 > namespaceRequestRateLimiter,
151 > shardRequestRateLimiter,
152 > params.Serializer,
153 > params.EventBlobCache,
154 > string(params.ClusterName),
155 > params.MetricsHandler,
156 > params.Logger,
157 > params.HealthSignals,
158 > params.EnableDataLossMetrics,
159 > params.EnableBestEffortDeleteTasksOnWorkflowUpdate,
160 > )
161 }
162
166 metricsHandler metrics.Handler,
167 logger log.ThrottledLogger,
168 > ) persistence.HealthSignalAggregator { fx.go
169 > if dynamicconfig.PersistenceHealthSignalMetricsEnabled.Get(dynamicCollection)() {
170 > aggregator := persistence.NewHealthSignalAggregator(
171 > dynamicconfig.PersistenceHealthSignalAggregationEnabled.Get(dynamicCollection)(),
172 > dynamicconfig.PersistenceHealthSignalPercentilesEnabled.Get(dynamicCollection),
173 > dynamicconfig.PersistenceHealthSignalWindowSize.Get(dynamicCollection)(),
174 > dynamicconfig.PersistenceHealthSignalBufferSize.Get(dynamicCollection)(),
175 > metricsHandler,
176 > logger,
177 > dynamicconfig.PersistenceHealthSignalLatencyWindowSize.Get(dynamicCollection)(),
178 > dynamicconfig.PersistenceHealthSignalLatencyWindowCount.Get(dynamicCollection)(),
179 > )
180 > lc.Append(fx.StopHook(aggregator.Stop))
181 > return aggregator
182 > }
183
184 return persistence.NoopHealthSignalAggregator
194 tracerProvider trace.TracerProvider,
195 serializer serialization.Serializer,
196 > ) persistence.DataStoreFactory { fx.go
197 > var dataStoreFactory persistence.DataStoreFactory
198 > defaultStoreCfg := cfg.DataStores[cfg.DefaultStore]
199 > switch {
200 case defaultStoreCfg.Cassandra != nil:
201 dataStoreFactory = cassandra.NewFactory(*defaultStoreCfg.Cassandra, r, string(clusterName), logger, metricsHandler, serializer)
202 > case defaultStoreCfg.SQL != nil: fx.go
203 > dataStoreFactory = sql.NewFactory(*defaultStoreCfg.SQL, r, string(clusterName), logger, metricsHandler, serializer)
204 case defaultStoreCfg.CustomDataStoreConfig != nil:
205 dataStoreFactory = abstractDataStoreFactory.NewFactory(*defaultStoreCfg.CustomDataStoreConfig, r, string(clusterName), logger, metricsHandler, serializer)
208 }
209
210 > if defaultStoreCfg.FaultInjection != nil { fx.go
211 dataStoreFactory = faultinjection.NewFaultInjectionDatastoreFactory(defaultStoreCfg.FaultInjection, dataStoreFactory)
212 }
213
214 > tracer := tracerProvider.Tracer(otel.ComponentPersistence) fx.go
215 > if otel.IsEnabled(tracer) {
216 dataStoreFactory = telemetry.NewTelemetryDataStoreFactory(dataStoreFactory, logger, tracer)
217 }
218
219 > return dataStoreFactory fx.go
220 }
221
222 > func DataStoreFactoryLifetimeHooks(lc fx.Lifecycle, f persistence.DataStoreFactory) { fx.go
223 > lc.Append(fx.StopHook(f.Close))
224 > }
225
226 > func managerProvider[T persistence.Closeable](newManagerFn func(Factory) (T, error)) func(Factory, fx.Lifecycle) (T, error) { fx.go
227 > return func(f Factory, lc fx.Lifecycle) (T, error) {
228 > manager, err := newManagerFn(f) // passing receiver (Factory) as first argument. fx.go
229 > if err != nil {
230 var unimpl *serviceerror.Unimplemented
231 if errors.As(err, &unimpl) {
236 return nilT, err
237 }
238 > lc.Append(fx.StopHook(manager.Close)) fx.go
239 > return manager, nil
240 }
241 }
go.temporal.io/server/common/persistence/sql/execution_tasks.go 92 covered LOC · 26 ranges

Open complete file

35 ctx context.Context,
36 request *p.GetHistoryTasksRequest,
37 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
38 > switch request.TaskCategory.Type() {
39 > case tasks.CategoryTypeImmediate: execution_tasks.go
40 > return m.getHistoryImmediateTasks(ctx, request)
41 > case tasks.CategoryTypeScheduled: execution_tasks.go
42 > return m.getHistoryScheduledTasks(ctx, request)
43 default:
44 return nil, serviceerror.NewInternalf("Unknown task category type: %v", request.TaskCategory)
81 ctx context.Context,
82 request *p.GetHistoryTasksRequest,
83 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
84 > // This is for backward compatiblity.
85 > // These task categories exist before the general history_immediate_tasks table is created,
86 > // so they have their own tables.
87 > categoryID := request.TaskCategory.ID()
88 > switch categoryID {
89 > case tasks.CategoryIDTransfer: execution_tasks.go
90 > return m.getTransferTasks(ctx, request)
91 > case tasks.CategoryIDVisibility: execution_tasks.go
92 > return m.getVisibilityTasks(ctx, request)
93 case tasks.CategoryIDReplication:
94 return m.getReplicationTasks(ctx, request)
95 }
96
97 > inclusiveMinTaskID, exclusiveMaxTaskID, err := getImmediateTaskReadRange(request) execution_tasks.go
98 > if err != nil {
99 return nil, err
100 }
101
102 > rows, err := m.DB.RangeSelectFromHistoryImmediateTasks(ctx, sqlplugin.HistoryImmediateTasksRangeFilter{ execution_tasks.go
103 > ShardID: request.ShardID,
104 > CategoryID: int32(categoryID),
105 > InclusiveMinTaskID: inclusiveMinTaskID,
106 > ExclusiveMaxTaskID: exclusiveMaxTaskID,
107 > PageSize: request.BatchSize,
108 > })
109 > if err != nil {
110 if err != sql.ErrNoRows {
111 return nil, serviceerror.NewUnavailablef(
114 }
115 }
116 > resp := &p.InternalGetHistoryTasksResponse{ execution_tasks.go
117 > Tasks: make([]p.InternalHistoryTask, len(rows)),
118 > }
119 > if len(rows) == 0 {
120 > return resp, nil
121 > }
122
123 for i, row := range rows {
199 ctx context.Context,
200 request *p.GetHistoryTasksRequest,
201 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
202 > // This is for backward compatiblity.
203 > // These task categories exist before the general history_scheduled_tasks table is created,
204 > // so they have their own tables.
205 > categoryID := request.TaskCategory.ID()
206 > if categoryID == tasks.CategoryIDTimer {
207 > return m.getTimerTasks(ctx, request) execution_tasks.go
208 > }
209
210 pageToken := &scheduledTaskPageToken{TaskID: math.MinInt64, Timestamp: request.InclusiveMinTaskKey.FireTime}
306 ctx context.Context,
307 request *p.GetHistoryTasksRequest,
308 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
309 > inclusiveMinTaskID, exclusiveMaxTaskID, err := getImmediateTaskReadRange(request)
310 > if err != nil {
311 return nil, err
312 }
313
314 > rows, err := m.DB.RangeSelectFromTransferTasks(ctx, sqlplugin.TransferTasksRangeFilter{ execution_tasks.go
315 > ShardID: request.ShardID,
316 > InclusiveMinTaskID: inclusiveMinTaskID,
317 > ExclusiveMaxTaskID: exclusiveMaxTaskID,
318 > PageSize: request.BatchSize,
319 > })
320 > if err != nil {
321 if err != sql.ErrNoRows {
322 return nil, serviceerror.NewUnavailablef("GetTransferTasks operation failed. Select failed. Error: %v", err)
323 }
324 }
325 > resp := &p.InternalGetHistoryTasksResponse{ execution_tasks.go
326 > Tasks: make([]p.InternalHistoryTask, len(rows)),
327 > }
328 > if len(rows) == 0 {
329 > return resp, nil execution_tasks.go
330 > }
331
332 for i, row := range rows {
376 ctx context.Context,
377 request *p.GetHistoryTasksRequest,
378 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
379 > pageToken := &scheduledTaskPageToken{TaskID: math.MinInt64, Timestamp: request.InclusiveMinTaskKey.FireTime}
380 > if len(request.NextPageToken) > 0 {
381 if err := pageToken.deserialize(request.NextPageToken); err != nil {
382 return nil, serviceerror.NewInternalf("error deserializing timerTaskPageToken: %v", err)
384 }
385
386 > rows, err := m.DB.RangeSelectFromTimerTasks(ctx, sqlplugin.TimerTasksRangeFilter{ execution_tasks.go
387 > ShardID: request.ShardID,
388 > InclusiveMinVisibilityTimestamp: pageToken.Timestamp,
389 > InclusiveMinTaskID: pageToken.TaskID,
390 > ExclusiveMaxVisibilityTimestamp: request.ExclusiveMaxTaskKey.FireTime,
391 > PageSize: request.BatchSize,
392 > })
393 >
394 > if err != nil && err != sql.ErrNoRows {
395 return nil, serviceerror.NewUnavailablef("GetTimerTasks operation failed. Select failed. Error: %v", err)
396 }
397
398 > resp := &p.InternalGetHistoryTasksResponse{Tasks: make([]p.InternalHistoryTask, 0, len(rows))} execution_tasks.go
399 > for _, row := range rows {
400 resp.Tasks = append(resp.Tasks, p.InternalHistoryTask{
401 Key: tasks.NewKey(row.VisibilityTimestamp, row.TaskID),
404 }
405
406 > if len(resp.Tasks) == request.BatchSize { execution_tasks.go
407 pageToken = &scheduledTaskPageToken{
408 TaskID: rows[request.BatchSize-1].TaskID + 1,
477 func getImmediateTaskReadRange(
478 request *p.GetHistoryTasksRequest,
479 > ) (inclusiveMinTaskID int64, exclusiveMaxTaskID int64, err error) { execution_tasks.go
480 > inclusiveMinTaskID = request.InclusiveMinTaskKey.TaskID
481 > if len(request.NextPageToken) > 0 {
482 inclusiveMinTaskID, err = deserializePageToken(request.NextPageToken)
483 if err != nil {
486 }
487
488 > return inclusiveMinTaskID, request.ExclusiveMaxTaskKey.TaskID, nil execution_tasks.go
489 }
490
693 ctx context.Context,
694 request *p.GetHistoryTasksRequest,
695 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
696 > inclusiveMinTaskID, exclusiveMaxTaskID, err := getImmediateTaskReadRange(request)
697 > if err != nil {
698 return nil, err
699 }
700
701 > rows, err := m.DB.RangeSelectFromVisibilityTasks(ctx, sqlplugin.VisibilityTasksRangeFilter{ execution_tasks.go
702 > ShardID: request.ShardID,
703 > InclusiveMinTaskID: inclusiveMinTaskID,
704 > ExclusiveMaxTaskID: exclusiveMaxTaskID,
705 > PageSize: request.BatchSize,
706 > })
707 > if err != nil {
708 if err != sql.ErrNoRows {
709 return nil, serviceerror.NewUnavailablef("GetVisibilityTasks operation failed. Select failed. Error: %v", err)
710 }
711 }
712 > resp := &p.InternalGetHistoryTasksResponse{ execution_tasks.go
713 > Tasks: make([]p.InternalHistoryTask, len(rows)),
714 > }
715 > if len(rows) == 0 {
716 > return resp, nil execution_tasks.go
717 > }
718
719 for i, row := range rows {
go.temporal.io/server/service/worker/fx.go 91 covered LOC · 12 ranges

Open complete file

59 fx.Provide(schedulerpb.NewSchedulerServiceLayeredClient),
60 fx.Provide(
61 > func(c resource.HistoryClient) dlq.HistoryClient { fx.go
62 > return c
63 > },
64 > func(m cluster.Metadata) dlq.CurrentClusterName {
65 > return dlq.CurrentClusterName(m.GetCurrentClusterName())
66 > },
67 > func(b client.Bean) dlq.TaskClientDialer {
68 > return dlq.TaskClientDialerFn(func(_ context.Context, address string) (dlq.TaskClient, error) {
69 c, err := b.GetRemoteAdminClient(address)
70 if err != nil {
94 logger log.Logger,
95 testHooks testhooks.TestHooks,
96 > ) nsreplication.TaskExecutor { fx.go
97 > return nsreplication.NewTaskExecutor(
98 > clusterMetadata.GetCurrentClusterName(),
99 > metadataManager,
100 > dataMerger,
101 > admitter,
102 > logger,
103 > testHooks,
104 > )
105 > }),
106 fx.Provide(nsreplication.NewNoopDataMerger),
107 fx.Provide(nsreplication.NewDefaultAdmitter),
113 )
114
115 > func ThrottledLoggerRpsFnProvider(serviceConfig *Config) resource.ThrottledLoggerRpsFn { fx.go
116 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
117 }
118
121 persistenceLazyLoadedServiceResolver service.PersistenceLazyLoadedServiceResolver,
122 logger log.SnTaggedLogger,
123 > ) service.PersistenceRateLimitingParams { fx.go
124 > return service.NewPersistenceRateLimitingParams(
125 > serviceConfig.PersistenceMaxQPS,
126 > serviceConfig.PersistenceGlobalMaxQPS,
127 > serviceConfig.PersistenceNamespaceMaxQPS,
128 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
129 > serviceConfig.PersistencePerShardNamespaceMaxQPS,
130 > serviceConfig.OperatorRPSRatio,
131 > serviceConfig.PersistenceQPSBurstRatio,
132 > serviceConfig.PersistenceDynamicRateLimitingParams,
133 > persistenceLazyLoadedServiceResolver,
134 > logger,
135 > )
136 > }
137
138 > func HostInfoProvider() (membership.HostInfo, error) { fx.go
139 > hn, err := os.Hostname()
140 > return membership.NewHostInfoFromAddress(hn), err
141 > }
142
143 func ServiceResolverProvider(
144 membershipMonitor membership.Monitor,
145 > ) (membership.ServiceResolver, error) { fx.go
146 > return membershipMonitor.GetResolver(primitives.WorkerService)
147 > }
148
149 func ConfigProvider(
150 dc *dynamicconfig.Collection,
151 persistenceConfig *config.Persistence,
152 > ) *Config { fx.go
153 > return NewConfig(
154 > dc,
155 > persistenceConfig,
156 > )
157 > }
158
159 func VisibilityManagerProvider(
169 chasmRegistry *chasm.Registry,
170 serializer serialization.Serializer,
171 > ) (manager.VisibilityManager, error) { fx.go
172 > return visibility.NewManager(
173 > *persistenceConfig,
174 > persistenceServiceResolver,
175 > customVisibilityStoreFactory,
176 > nil, // worker visibility never write
177 > saProvider,
178 > searchAttributesMapperProvider,
179 > namespaceRegistry,
180 > chasmRegistry,
181 > serviceConfig.VisibilityPersistenceMaxReadQPS,
182 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
183 > serviceConfig.OperatorRPSRatio,
184 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
185 > serviceConfig.EnableReadFromSecondaryVisibility,
186 > serviceConfig.VisibilityEnableShadowReadMode,
187 > dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff), // worker visibility never write
188 > serviceConfig.VisibilityDisableOrderByClause,
189 > serviceConfig.VisibilityEnableManualPagination,
190 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
191 > metricsHandler,
192 > logger,
193 > serializer,
194 > )
195 > }
196
197 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
198 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
199 > }
200
201 type perNamespaceWorkerManagerInitParams struct {
210 }
211
212 > func PerNamespaceWorkerManagerProvider(params perNamespaceWorkerManagerInitParams) *PerNamespaceWorkerManager { fx.go
213 > return NewPerNamespaceWorkerManager(
214 > params.Logger,
215 > params.SdkClientFactory,
216 > params.NamespaceRegistry,
217 > params.HostName,
218 > params.Config,
219 > params.ClusterMetadata,
220 > params.Components,
221 > primitives.PerNSWorkerTaskQueue,
222 > )
223 > }
224
225 > func ServerProvider(rpcFactory common.RPCFactory, logger log.Logger) *grpc.Server { fx.go
226 > opts, err := rpcFactory.GetInternodeGRPCServerOptions()
227 > if err != nil {
228 logger.Fatal("Failed to get gRPC server options", tag.Error(err))
229 }
230 > return grpc.NewServer(opts...) fx.go
231 }
go.temporal.io/server/common/tasks/sequential_scheduler.go 90 covered LOC · 20 ranges

Open complete file

52 taskQueueFactory SequentialTaskQueueFactory[T],
53 logger log.Logger,
54 > ) *SequentialScheduler[T] { sequential_scheduler.go
55 > return &SequentialScheduler[T]{
56 > status: common.DaemonStatusInitialized,
57 > shutdownChan: make(chan struct{}),
58 > options: options,
59 >
60 > logger: logger,
61 >
62 > queueFactory: taskQueueFactory,
63 > queueChan: make(chan SequentialTaskQueue[T], options.QueueSize),
64 > queues: collection.NewShardedConcurrentTxMap(1024, taskQueueHashFn),
65 > }
66 > }
67
68 > func (s *SequentialScheduler[T]) Start() { sequential_scheduler.go
69 > if !atomic.CompareAndSwapInt32(
70 > &s.status,
71 > common.DaemonStatusInitialized,
72 > common.DaemonStatusStarted,
73 > ) {
74 return
75 }
76
77 > initialWorkerCount, workerCountSubscriptionCancelFn := s.options.WorkerCount(s.updateWorkerCount) sequential_scheduler.go
78 > s.workerCountSubscriptionCancelFn = workerCountSubscriptionCancelFn
79 > s.updateWorkerCount(initialWorkerCount)
80 >
81 > s.logger.Info("sequential scheduler started")
82 }
83
84 > func (s *SequentialScheduler[T]) Stop() { sequential_scheduler.go
85 > if !atomic.CompareAndSwapInt32(
86 > &s.status,
87 > common.DaemonStatusStarted,
88 > common.DaemonStatusStopped,
89 > ) {
90 return
91 }
92
93 > close(s.shutdownChan) sequential_scheduler.go
94 > s.workerCountSubscriptionCancelFn()
95 > s.updateWorkerCount(0)
96 > // must be called after the close of the shutdownChan
97 > s.drainTasks()
98 >
99 > go func() {
100 > if success := common.AwaitWaitGroup(&s.shutdownWG, time.Minute); !success {
101 s.logger.Warn("sequential scheduler timed out waiting for workers")
102 }
103 }()
104 > s.logger.Info("sequential scheduler stopped") sequential_scheduler.go
105 }
106
199 }
200
201 > func (s *SequentialScheduler[T]) updateWorkerCount(targetWorkerNum int) { sequential_scheduler.go
202 > s.workerLock.Lock()
203 > defer s.workerLock.Unlock()
204 >
205 > if s.isStopped() {
206 > // Always set the value to 0 when scheduler is stopped, sequential_scheduler.go
207 > // in case there's a race condition between subscription callback invocation
208 > // and the invocation made from Stop()
209 > targetWorkerNum = 0
210 > }
211
212 > if targetWorkerNum < 0 { sequential_scheduler.go
213 s.logger.Error("Target worker pool size is negative. Please fix the dynamic config.", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum))
214 return
215 }
216
217 > currentWorkerNum := len(s.workerShutdownCh) sequential_scheduler.go
218 > if targetWorkerNum == currentWorkerNum {
219 return
220 }
221
222 > if targetWorkerNum > currentWorkerNum { sequential_scheduler.go
223 > s.startWorkers(targetWorkerNum - currentWorkerNum)
224 > } else {
225 > s.stopWorkers(currentWorkerNum - targetWorkerNum) sequential_scheduler.go
226 > }
227
228 > s.logger.Info("Update worker pool size", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum)) sequential_scheduler.go
229 }
230
231 func (s *SequentialScheduler[T]) startWorkers(
232 count int,
234 > for range count {
235 > shutdownCh := make(chan struct{})
236 > s.workerShutdownCh = append(s.workerShutdownCh, shutdownCh)
237 >
238 > s.shutdownWG.Add(1)
239 > go s.pollTaskQueue(shutdownCh)
240 > }
241 }
242
243 func (s *SequentialScheduler[T]) stopWorkers(
244 count int,
246 > shutdownChToClose := s.workerShutdownCh[:count]
247 > s.workerShutdownCh = s.workerShutdownCh[count:]
248 >
249 > for _, shutdownCh := range shutdownChToClose {
250 > close(shutdownCh)
251 > }
252 }
253
254 > func (s *SequentialScheduler[T]) pollTaskQueue(workerShutdownCh <-chan struct{}) { sequential_scheduler.go
255 > defer s.shutdownWG.Done()
256 >
257 > for {
258 > select {
259 > case <-s.shutdownChan: sequential_scheduler.go
260 > s.drainTasks()
261 > return
262 case <-workerShutdownCh:
263 return
345 }
346
347 > func (s *SequentialScheduler[T]) drainTasks() { sequential_scheduler.go
348 > LoopDrainQueues:
349 > for {
350 > select {
351 case queue := <-s.queueChan:
352 LoopDrainSingleQueue:
362 }
363 }
364 > default: sequential_scheduler.go
365 > break LoopDrainQueues
366 }
367 }
368 }
369
370 > func (s *SequentialScheduler[T]) isStopped() bool { sequential_scheduler.go
371 > return atomic.LoadInt32(&s.status) == common.DaemonStatusStopped
372 > }
go.temporal.io/server/common/tasks/fifo_scheduler.go 87 covered LOC · 23 ranges

Open complete file

42 options *FIFOSchedulerOptions,
43 logger log.Logger,
44 > ) *FIFOScheduler[T] { fifo_scheduler.go
45 > return &FIFOScheduler[T]{
46 > status: common.DaemonStatusInitialized,
47 > options: options,
48 >
49 > logger: logger,
50 >
51 > tasksChan: make(chan T, options.QueueSize),
52 > }
53 > }
54
55 > func (f *FIFOScheduler[T]) Start() { fifo_scheduler.go
56 > if !atomic.CompareAndSwapInt32(
57 > &f.status,
58 > common.DaemonStatusInitialized,
59 > common.DaemonStatusStarted,
60 > ) {
61 return
62 }
63
64 > initialWorkerCount, workerCountSubscriptionCancelFn := f.options.WorkerCount(f.updateWorkerCount) fifo_scheduler.go
65 > f.workerCountSubscriptionCancelFn = workerCountSubscriptionCancelFn
66 > f.updateWorkerCount(initialWorkerCount)
67 >
68 > f.logger.Info("fifo scheduler started")
69 }
70
71 > func (f *FIFOScheduler[T]) Stop() { fifo_scheduler.go
72 > if !atomic.CompareAndSwapInt32(
73 > &f.status,
74 > common.DaemonStatusStarted,
75 > common.DaemonStatusStopped,
76 > ) {
77 return
78 }
79
80 > f.workerCountSubscriptionCancelFn() fifo_scheduler.go
81 > f.updateWorkerCount(0)
82 > f.drainTasks()
83 >
84 > go func() {
85 > if success := common.AwaitWaitGroup(&f.shutdownWG, time.Minute); !success {
86 f.logger.Warn("fifo scheduler timed out waiting for workers")
87 }
88 }()
89 > f.logger.Info("fifo scheduler stopped") fifo_scheduler.go
90 }
91
109 }
110
111 > func (f *FIFOScheduler[T]) updateWorkerCount(targetWorkerNum int) { fifo_scheduler.go
112 > f.workerLock.Lock()
113 > defer f.workerLock.Unlock()
114 >
115 > if f.isStopped() {
116 > // Always set the value to 0 when scheduler is stopped, fifo_scheduler.go
117 > // in case there's a race condition between subscription callback invocation
118 > // and the invocation made from Stop()
119 > targetWorkerNum = 0
120 > }
121
122 > if targetWorkerNum < 0 { fifo_scheduler.go
123 f.logger.Error("Target worker pool size is negative. Please fix the dynamic config.", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum))
124 return
125 }
126
127 > currentWorkerNum := len(f.workerShutdownCh) fifo_scheduler.go
128 > if targetWorkerNum == currentWorkerNum {
129 return
130 }
131
132 > if targetWorkerNum > currentWorkerNum { fifo_scheduler.go
133 > f.startWorkers(targetWorkerNum - currentWorkerNum)
134 > } else {
135 > f.stopWorkers(currentWorkerNum - targetWorkerNum) fifo_scheduler.go
136 > }
137
138 > f.logger.Info("Update worker pool size", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum)) fifo_scheduler.go
139 }
140
141 func (f *FIFOScheduler[T]) startWorkers(
142 count int,
143 > ) { fifo_scheduler.go
144 > for range count {
145 > shutdownCh := make(chan struct{})
146 > f.workerShutdownCh = append(f.workerShutdownCh, shutdownCh)
147 >
148 > f.shutdownWG.Add(1)
149 > go f.processTask(shutdownCh)
150 > }
151 }
152
153 func (f *FIFOScheduler[T]) stopWorkers(
154 count int,
155 > ) { fifo_scheduler.go
156 > shutdownChToClose := f.workerShutdownCh[:count]
157 > f.workerShutdownCh = f.workerShutdownCh[count:]
158 >
159 > for _, shutdownCh := range shutdownChToClose {
160 > close(shutdownCh)
161 > }
162 }
163
164 func (f *FIFOScheduler[T]) processTask(
165 shutdownCh chan struct{},
166 > ) { fifo_scheduler.go
167 > defer f.shutdownWG.Done()
168 >
169 > for {
170 > if f.isStopped() {
171 return
172 }
173
174 > select { fifo_scheduler.go
175 case <-shutdownCh:
176 return
177 > default: fifo_scheduler.go
178 }
179
180 > select { fifo_scheduler.go
181 case task := <-f.tasksChan:
182 f.executeTask(task)
183
184 > case <-shutdownCh: fifo_scheduler.go
185 > return
186 }
187 }
215 }
216
217 > func (f *FIFOScheduler[T]) drainTasks() { fifo_scheduler.go
218 > LoopDrain:
219 > for {
220 > select {
221 case task := <-f.tasksChan:
222 task.Abort()
223 > default: fifo_scheduler.go
224 > break LoopDrain
225 }
226 }
227 }
228
229 > func (f *FIFOScheduler[T]) isStopped() bool { fifo_scheduler.go
230 > return atomic.LoadInt32(&f.status) == common.DaemonStatusStopped
231 > }
go.temporal.io/server/common/persistence/query_util.go 86 covered LOC · 33 ranges

Open complete file

55 func LoadAndSplitQueryFromReaders(
56 readers []io.Reader,
57 > ) ([]string, error) { query_util.go
58 > result := make([]string, 0, querySliceDefaultSize)
59 > for _, r := range readers {
60 > content, err := io.ReadAll(r)
61 > if err != nil {
62 return nil, fmt.Errorf("error reading contents: %w", err)
63 }
64 > n := len(content) query_util.go
65 > contentStr := string(bytes.ToLower(content))
66 > for i, j := 0, 0; i < n; i = j {
67 > // stack to keep track of open parenthesis/blocks
68 > var st []byte
69 > var stmtBuilder strings.Builder
70 >
71 > stmtLoop:
72 > for ; j < n; j++ {
73 > switch contentStr[j] {
74 > case queryDelimiter: query_util.go
75 > if len(st) == 0 {
76 > j++
77 > break stmtLoop
78 }
79
80 > case sqlLeftParenthesis: query_util.go
81 > st = append(st, sqlLeftParenthesis)
82
83 > case sqlRightParenthesis: query_util.go
84 > if len(st) == 0 || st[len(st)-1] != sqlLeftParenthesis {
85 return nil, fmt.Errorf("error reading contents: unmatched right parenthesis")
86 }
87 > st = st[:len(st)-1] query_util.go
88
89 case sqlDoubleDollarKeyword[0]:
99 }
100
101 > case sqlIfKeyword[0]: query_util.go
102 > if !hasWordAt(contentStr, sqlIfKeyword, j) {
103 > continue
104 }
105 if hasWordsBefore(contentStr, j-1, sqlAddKeyword, sqlColumnKeyword) ||
112 j += len(sqlIfKeyword) - 1
113
114 > case sqlLoopKeyword[0]: query_util.go
115 > if !hasWordAt(contentStr, sqlLoopKeyword, j) {
116 > continue
117 }
118 st = append(st, sqlLoopKeyword[0])
119 j += len(sqlLoopKeyword) - 1
120
121 > case sqlBeginKeyword[0]: query_util.go
122 > if hasWordAt(contentStr, sqlBeginKeyword, j) {
123 > st = append(st, sqlBeginKeyword[0]) query_util.go
124 > j += len(sqlBeginKeyword) - 1
125 > }
126
127 > case sqlEndKeyword[0]: query_util.go
128 > if !hasWordAt(contentStr, sqlEndKeyword, j) {
129 > continue
130 }
131 > if ok, after := hasWordAfter(contentStr, sqlIfKeyword, j+len(sqlEndKeyword)); ok { query_util.go
132 if len(st) == 0 || st[len(st)-1] != sqlIfKeyword[0] {
133 return nil, errors.New("error reading contents: unmatched `END IF` keyword")
135 st = st[:len(st)-1]
136 j = after + len(sqlIfKeyword) - 1
137 > } else if ok, after := hasWordAfter(contentStr, sqlLoopKeyword, j+len(sqlEndKeyword)); ok { query_util.go
138 //nolint:revive
139 if len(st) == 0 || st[len(st)-1] != sqlLoopKeyword[0] {
142 st = st[:len(st)-1]
143 j = after + len(sqlLoopKeyword) - 1
144 > } else { query_util.go
145 > if len(st) == 0 || st[len(st)-1] != sqlBeginKeyword[0] {
146 return nil, errors.New("error reading contents: unmatched `END` keyword")
147 }
148 > st = st[:len(st)-1] query_util.go
149 > j += len(sqlEndKeyword) - 1
150 }
151
152 > case sqlSingleQuote, sqlDoubleQuote: query_util.go
153 > quote := contentStr[j]
154 > j++
155 > for j < n && contentStr[j] != quote {
156 > j++
157 > }
158 > if j == n {
159 return nil, fmt.Errorf("error reading contents: unmatched quotes")
160 }
161
162 > case sqlLineComment[0]: query_util.go
163 > if j+len(sqlLineComment) <= n && contentStr[j:j+len(sqlLineComment)] == sqlLineComment {
164 > _, _ = stmtBuilder.Write(bytes.TrimRight(content[i:j], " "))
165 > for j < n && contentStr[j] != '\n' {
166 > j++
167 > }
168 > i = j
169 }
170
171 > default: query_util.go
172 // no-op: generic character
173 }
174 }
175
176 > if len(st) > 0 { query_util.go
177 switch st[len(st)-1] {
178 case sqlLeftParenthesis:
186 }
187
188 > _, _ = stmtBuilder.Write(content[i:j]) query_util.go
189 > stmt := strings.TrimSpace(stmtBuilder.String())
190 > if stmt == "" {
191 > continue query_util.go
192 }
193 > result = append(result, stmt) query_util.go
194 }
195 }
196 > return result, nil query_util.go
197 }
198
199 // hasWordAt is a simple test to check if it matches the whole word:
200 // it checks if the adjacent characters are not alphanumeric if they exist.
201 > func hasWordAt(s, word string, pos int) bool { query_util.go
202 > if pos+len(word) > len(s) || s[pos:pos+len(word)] != word {
203 > return false
204 > }
205 > if pos > 0 && isAlphanumeric(s[pos-1]) { query_util.go
206 > return false query_util.go
207 > }
208 > if pos+len(word) < len(s) && isAlphanumeric(s[pos+len(word)]) { query_util.go
209 > return false query_util.go
210 > }
211 > return true query_util.go
212 }
213
214 // hasWordAfter checks if the given word appears after position pos in s,
215 // separated by at least one space, and is a whole word.
216 > func hasWordAfter(s, word string, pos int) (bool, int) { query_util.go
217 > after := pos
218 > for after < len(s) && unicode.IsSpace(rune(s[after])) {
219 after++
220 }
221 > if after == pos { query_util.go
222 > return false, after query_util.go
223 > }
224 return hasWordAt(s, word, after), after
225 }
254 }
255
256 > func isAlphanumeric(c byte) bool { query_util.go
257 > return unicode.IsLetter(rune(c)) || unicode.IsDigit(rune(c))
258 > }
go.temporal.io/server/common/metrics/config.go 84 covered LOC · 27 ranges

Open complete file

288 // Current priority order is:
289 // statsd > prometheus
290 > func NewScope(logger log.Logger, c *Config) tally.Scope { config.go
291 > if c.Statsd != nil {
292 return newStatsdScope(logger, c)
293 }
294 > if c.Prometheus != nil { config.go
295 > sanitizeOptions, err := convertSanitizeOptionsToTally(c.Prometheus) config.go
296 > if err != nil {
297 logger.Fatal("invalid sanitize options input on prometheus config", tag.Error(err))
298 return nil
299 }
300
301 > if c.Prometheus.LoggerRPS > 0 { config.go
302 logger = log.NewThrottledLogger(logger, func() float64 { return c.Prometheus.LoggerRPS })
303 }
304
305 > return newPrometheusScope( config.go
306 > logger,
307 > convertPrometheusConfigToTally(&c.ClientConfig, c.Prometheus),
308 > sanitizeOptions,
309 > &c.ClientConfig,
310 > )
311 }
312 return tally.NoopScope
313 }
314
315 > func convertSanitizeOptionsToTally(config *PrometheusConfig) (tally.SanitizeOptions, error) { config.go
316 > if config.SanitizeOptions == nil {
317 > return defaultTallySanitizeOptions, nil config.go
318 > }
319
320 return config.SanitizeOptions.toTally()
324 clientConfig *ClientConfig,
325 config *PrometheusConfig,
326 > ) *prometheus.Configuration { config.go
327 > defaultObjectives := make([]prometheus.SummaryObjective, len(config.DefaultSummaryObjectives))
328 > for i, item := range config.DefaultSummaryObjectives {
329 defaultObjectives[i].AllowedError = item.AllowedError
330 defaultObjectives[i].Percentile = item.Percentile
331 }
332
333 > return &prometheus.Configuration{ config.go
334 > HandlerPath: config.HandlerPath,
335 > ListenNetwork: config.ListenNetwork,
336 > ListenAddress: config.ListenAddress,
337 > TimerType: "histogram",
338 > DefaultHistogramBuckets: buildTallyTimerHistogramBuckets(clientConfig, config),
339 > DefaultSummaryObjectives: defaultObjectives,
340 > OnError: config.OnError,
341 > }
342 }
343
345 clientConfig *ClientConfig,
346 config *PrometheusConfig,
347 > ) []prometheus.HistogramObjective { config.go
348 > if len(config.DefaultHistogramBuckets) > 0 {
349 result := make([]prometheus.HistogramObjective, len(config.DefaultHistogramBuckets))
350 for i, item := range config.DefaultHistogramBuckets {
354 }
355
356 > if len(config.DefaultHistogramBoundaries) > 0 { config.go
357 result := make([]prometheus.HistogramObjective, 0, len(config.DefaultHistogramBoundaries))
358 for _, value := range config.DefaultHistogramBoundaries {
364 }
365
366 > boundaries := clientConfig.PerUnitHistogramBoundaries[Milliseconds] config.go
367 > result := make([]prometheus.HistogramObjective, 0, len(boundaries))
368 > for _, boundary := range boundaries {
369 > result = append(result, prometheus.HistogramObjective{ config.go
370 > Upper: boundary / float64(time.Second/time.Millisecond), // convert milliseconds to seconds
371 > })
372 > }
373 > return result config.go
374 }
375
376 > func setDefaultPerUnitHistogramBoundaries(clientConfig *ClientConfig) { config.go
377 > buckets := maps.Clone(defaultPerUnitHistogramBoundaries)
378 >
379 > // In config, when overwrite default buckets, we use [dimensionless / miliseconds / bytes] as keys.
380 > // But in code, we use [1 / ms / By] as key (to align with otel unit definition). So we do conversion here.
381 > if bucket, ok := clientConfig.PerUnitHistogramBoundaries[UnitNameDimensionless]; ok {
382 buckets[Dimensionless] = bucket
383 }
384 > if bucket, ok := clientConfig.PerUnitHistogramBoundaries[UnitNameMilliseconds]; ok { config.go
385 buckets[Milliseconds] = bucket
386 }
387 > if bucket, ok := clientConfig.PerUnitHistogramBoundaries[UnitNameBytes]; ok { config.go
388 buckets[Bytes] = bucket
389 }
390
391 > bucketInSeconds := make([]float64, len(buckets[Milliseconds])) config.go
392 > for idx, boundary := range buckets[Milliseconds] {
393 > bucketInSeconds[idx] = boundary / float64(time.Second/time.Millisecond)
394 > }
395 > buckets[Seconds] = bucketInSeconds
396 >
397 > clientConfig.PerUnitHistogramBoundaries = buckets
398 }
399
436 sanitizeOptions tally.SanitizeOptions,
437 clientConfig *ClientConfig,
438 > ) tally.Scope { config.go
439 > reporter, err := config.NewReporter(
440 > prometheus.ConfigurationOptions{
441 > Registry: prom.NewRegistry(),
442 > OnError: func(err error) {
443 logger.Warn("error in prometheus reporter", tag.Error(err))
444 },
445 },
446 )
447 > if err != nil { config.go
448 logger.Fatal("error creating prometheus reporter", tag.Error(err))
449 }
450 > scopeOpts := tally.ScopeOptions{ config.go
451 > Tags: clientConfig.Tags,
452 > CachedReporter: reporter,
453 > Separator: prometheus.DefaultSeparator,
454 > SanitizeOptions: &sanitizeOptions,
455 > Prefix: clientConfig.Prefix,
456 > }
457 > scope, _ := tally.NewRootScope(scopeOpts, time.Second)
458 > return scope
459 }
460
461 // MetricsHandlerFromConfig is used at startup to construct a MetricsHandler
462 > func MetricsHandlerFromConfig(logger log.Logger, c *Config) (Handler, error) { config.go
463 > if c == nil {
464 return NoopMetricsHandler, nil
465 }
466
467 > setDefaultPerUnitHistogramBoundaries(&c.ClientConfig) config.go
468 >
469 > fatalOnListenerError := true
470 > if c.Statsd != nil && c.Statsd.Framework == FrameworkOpentelemetry {
471 // create opentelemetry provider with just statsd
472 otelProvider, err := NewOpenTelemetryProviderWithStatsd(logger, c.Statsd, &c.ClientConfig)
477 }
478
479 > if c.Prometheus != nil && c.Prometheus.Framework == FrameworkOpentelemetry { config.go
480 // create opentelemetry provider with just prometheus
481 otelProvider, err := NewOpenTelemetryProviderWithPrometheus(logger, c.Prometheus, &c.ClientConfig, fatalOnListenerError)
487
488 // fallback to tally if no framework is specified
489 > return NewTallyMetricsHandler( config.go
490 > c.ClientConfig,
491 > NewScope(logger, c),
492 > ), nil
493 }
494
495 > func configExcludeTags(cfg ClientConfig) map[string]map[string]struct{} { config.go
496 > tagsToFilter := make(map[string]map[string]struct{})
497 > for key, val := range cfg.ExcludeTags {
498 exclusions := make(map[string]struct{})
499 for _, val := range val {
502 tagsToFilter[key] = exclusions
503 }
504 > return tagsToFilter config.go
505 }
506
go.temporal.io/server/api/persistence/v1/predicates.pb.go 83 covered LOC · 23 ranges

Open complete file

57 func (*Predicate) ProtoMessage() {}
58
59 > func (x *Predicate) ProtoReflect() protoreflect.Message { predicates.pb.go
60 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[0]
61 > if x != nil {
62 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
63 > if ms.LoadMessageInfo() == nil {
64 > ms.StoreMessageInfo(mi)
65 > }
66 > return ms
67 }
68 > return mi.MessageOf(x) predicates.pb.go
69 }
70
261 func (*UniversalPredicateAttributes) ProtoMessage() {}
262
263 > func (x *UniversalPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
264 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[1]
265 > if x != nil {
266 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
267 if ms.LoadMessageInfo() == nil {
297 func (*EmptyPredicateAttributes) ProtoMessage() {}
298
299 > func (x *EmptyPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
300 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[2]
301 > if x != nil {
302 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
303 if ms.LoadMessageInfo() == nil {
334 func (*AndPredicateAttributes) ProtoMessage() {}
335
336 > func (x *AndPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
337 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[3]
338 > if x != nil {
339 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
340 if ms.LoadMessageInfo() == nil {
378 func (*OrPredicateAttributes) ProtoMessage() {}
379
380 > func (x *OrPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
381 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[4]
382 > if x != nil {
383 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
384 if ms.LoadMessageInfo() == nil {
422 func (*NotPredicateAttributes) ProtoMessage() {}
423
424 > func (x *NotPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
425 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[5]
426 > if x != nil {
427 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
428 if ms.LoadMessageInfo() == nil {
466 func (*NamespaceIdPredicateAttributes) ProtoMessage() {}
467
468 > func (x *NamespaceIdPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
469 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[6]
470 > if x != nil {
471 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
472 if ms.LoadMessageInfo() == nil {
510 func (*TaskTypePredicateAttributes) ProtoMessage() {}
511
512 > func (x *TaskTypePredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
513 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[7]
514 > if x != nil {
515 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
516 if ms.LoadMessageInfo() == nil {
554 func (*DestinationPredicateAttributes) ProtoMessage() {}
555
556 > func (x *DestinationPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
557 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[8]
558 > if x != nil {
559 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
560 if ms.LoadMessageInfo() == nil {
598 func (*OutboundTaskGroupPredicateAttributes) ProtoMessage() {}
599
600 > func (x *OutboundTaskGroupPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
601 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[9]
602 > if x != nil {
603 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
604 if ms.LoadMessageInfo() == nil {
642 func (*OutboundTaskPredicateAttributes) ProtoMessage() {}
643
644 > func (x *OutboundTaskPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
645 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[10]
646 > if x != nil {
647 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
648 if ms.LoadMessageInfo() == nil {
828 }
829
830 > func init() { file_temporal_server_api_persistence_v1_predicates_proto_init() } predicates.pb.go
831 > func file_temporal_server_api_persistence_v1_predicates_proto_init() {
832 > if File_temporal_server_api_persistence_v1_predicates_proto != nil {
833 > return
834 > }
835 > file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[0].OneofWrappers = []any{
836 > (*Predicate_UniversalPredicateAttributes)(nil),
837 > (*Predicate_EmptyPredicateAttributes)(nil),
838 > (*Predicate_AndPredicateAttributes)(nil),
839 > (*Predicate_OrPredicateAttributes)(nil),
840 > (*Predicate_NotPredicateAttributes)(nil),
841 > (*Predicate_NamespaceIdPredicateAttributes)(nil),
842 > (*Predicate_TaskTypePredicateAttributes)(nil),
843 > (*Predicate_DestinationPredicateAttributes)(nil),
844 > (*Predicate_OutboundTaskGroupPredicateAttributes)(nil),
845 > (*Predicate_OutboundTaskPredicateAttributes)(nil),
846 > }
847 > type x struct{}
848 > out := protoimpl.TypeBuilder{
849 > File: protoimpl.DescBuilder{
850 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
851 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_predicates_proto_rawDesc), len(file_temporal_server_api_persistence_v1_predicates_proto_rawDesc)),
852 > NumEnums: 0,
853 > NumMessages: 12,
854 > NumExtensions: 0,
855 > NumServices: 0,
856 > },
857 > GoTypes: file_temporal_server_api_persistence_v1_predicates_proto_goTypes,
858 > DependencyIndexes: file_temporal_server_api_persistence_v1_predicates_proto_depIdxs,
859 > MessageInfos: file_temporal_server_api_persistence_v1_predicates_proto_msgTypes,
860 > }.Build()
861 > File_temporal_server_api_persistence_v1_predicates_proto = out.File
862 > file_temporal_server_api_persistence_v1_predicates_proto_goTypes = nil
863 > file_temporal_server_api_persistence_v1_predicates_proto_depIdxs = nil
864 }
go.temporal.io/server/client/clientfactory.go 83 covered LOC · 14 ranges

Open complete file

73
74 // NewFactoryProvider creates a default implementation of FactoryProvider.
75 > func NewFactoryProvider() FactoryProvider { clientfactory.go
76 > return &factoryProviderImpl{}
77 > }
78
79 // NewFactory creates an instance of client factory that knows how to dispatch RPC calls.
87 logger log.Logger,
88 throttledLogger log.Logger,
89 > ) Factory { clientfactory.go
90 > return &rpcClientFactory{
91 > rpcFactory: rpcFactory,
92 > monitor: monitor,
93 > metricsHandler: metricsHandler,
94 > dynConfig: dc,
95 > testHooks: testHooks,
96 > numberOfHistoryShards: numberOfHistoryShards,
97 > logger: logger,
98 > throttledLogger: throttledLogger,
99 > }
100 > }
101
102 > func (cf *rpcClientFactory) NewHistoryClientWithTimeout(timeout time.Duration) (historyservice.HistoryServiceClient, error) { clientfactory.go
103 > resolver, err := cf.monitor.GetResolver(primitives.HistoryService)
104 > if err != nil {
105 return nil, err
106 }
107 > client := history.NewClient( clientfactory.go
108 > cf.dynConfig,
109 > resolver,
110 > cf.logger,
111 > cf.numberOfHistoryShards,
112 > cf.rpcFactory,
113 > timeout,
114 > )
115 > if cf.metricsHandler != nil {
116 > client = history.NewMetricClient(client, cf.metricsHandler, cf.logger, cf.throttledLogger)
117 > }
118 > return client, nil
119 }
120
123 timeout time.Duration,
124 longPollTimeout time.Duration,
125 > ) (matchingservice.MatchingServiceClient, error) { clientfactory.go
126 > resolver, err := cf.monitor.GetResolver(primitives.MatchingService)
127 > if err != nil {
128 return nil, err
129 }
130
131 > keyResolver := newServiceKeyResolver(resolver) clientfactory.go
132 > clientProvider := func(clientKey string) (any, func() error, error) {
133 connection := cf.rpcFactory.CreateMatchingGRPCConnection(clientKey)
134 return matchingservice.NewMatchingServiceClient(connection), connection.Close, nil
135 }
136 > client := matching.NewClient( clientfactory.go
137 > timeout,
138 > longPollTimeout,
139 > common.NewClientCache(keyResolver, clientProvider, cf.logger),
140 > cf.metricsHandler,
141 > cf.logger,
142 > matching.NewLoadBalancer(namespaceIDToName, cf.dynConfig, cf.testHooks),
143 > dynamicconfig.MatchingSpreadRoutingBatchSize.Get(cf.dynConfig),
144 > resolver,
145 > dynamicconfig.MatchingConnectionCloseDelay.Get(cf.dynConfig),
146 > )
147 >
148 > if cf.metricsHandler != nil {
149 > client = matching.NewMetricClient(client, cf.metricsHandler, cf.logger, cf.throttledLogger)
150 > }
151 > return client, nil
152
153 }
166 timeout time.Duration,
167 longPollTimeout time.Duration,
168 > ) (grpc.ClientConnInterface, workflowservice.WorkflowServiceClient, error) { clientfactory.go
169 > connection := cf.rpcFactory.CreateLocalFrontendGRPCConnection()
170 > client := workflowservice.NewWorkflowServiceClient(connection)
171 > return connection, cf.newFrontendClient(client, timeout, longPollTimeout), nil
172 > }
173
174 func (cf *rpcClientFactory) NewRemoteAdminClientWithTimeout(
185 timeout time.Duration,
186 longPollTimeout time.Duration,
187 > ) (adminservice.AdminServiceClient, error) { clientfactory.go
188 > connection := cf.rpcFactory.CreateLocalFrontendGRPCConnection()
189 > client := adminservice.NewAdminServiceClient(connection)
190 > return cf.newAdminClient(client, timeout, longPollTimeout), nil
191 > }
192
193 func (cf *rpcClientFactory) newAdminClient(
195 timeout time.Duration,
196 longPollTimeout time.Duration,
197 > ) adminservice.AdminServiceClient { clientfactory.go
198 > client = admin.NewClient(timeout, longPollTimeout, client)
199 > if cf.metricsHandler != nil {
200 > client = admin.NewMetricClient(client, cf.metricsHandler, cf.throttledLogger)
201 > }
202 > return client
203 }
204
207 timeout time.Duration,
208 longPollTimeout time.Duration,
209 > ) workflowservice.WorkflowServiceClient { clientfactory.go
210 > client = frontend.NewClient(timeout, longPollTimeout, client)
211 > if cf.metricsHandler != nil {
212 > client = frontend.NewMetricClient(client, cf.metricsHandler, cf.throttledLogger)
213 > }
214 > return client
215 }
216
217 > func newServiceKeyResolver(resolver membership.ServiceResolver) *serviceKeyResolverImpl { clientfactory.go
218 > return &serviceKeyResolverImpl{
219 > resolver: resolver,
220 > }
221 > }
222
223 // Lookup returns the address for a node within a batch. key contains the key (including batch
224 // number), and index is the index within the batch. If not using batches, index should be 0.
225 // Note that Lookup(key) and LookupN(key, n)[0] are equal.
226 > func (r *serviceKeyResolverImpl) Lookup(key string, index int) (string, error) { clientfactory.go
227 > hosts := r.resolver.LookupN(key, index+1)
228 > if len(hosts) == 0 {
229 > return "", membership.ErrInsufficientHosts clientfactory.go
230 > }
231 if index >= len(hosts) {
232 index %= len(hosts)
go.temporal.io/server/service/history/queues/queue_immediate.go 83 covered LOC · 18 ranges

Open complete file

41 factory ExecutableFactory,
42 taskPostProcessor taskPostProcessorFn,
43 > ) *immediateQueue { queue_immediate.go
44 > paginationFnProvider := func(r Range) collection.PaginationFn[tasks.Task] {
45 > return func(paginationToken []byte) ([]tasks.Task, []byte, error) {
46 > ctx, cancel := newQueueIOContext()
47 > defer cancel()
48 >
49 > request := &persistence.GetHistoryTasksRequest{
50 > ShardID: shard.GetShardID(),
51 > TaskCategory: category,
52 > InclusiveMinTaskKey: r.InclusiveMin,
53 > ExclusiveMaxTaskKey: r.ExclusiveMax,
54 > BatchSize: options.BatchSize(),
55 > NextPageToken: paginationToken,
56 > }
57 >
58 > resp, err := shard.GetHistoryTasks(ctx, request)
59 > if err != nil {
60 return nil, nil, err
61 }
62
63 > if taskPostProcessor != nil { queue_immediate.go
64 > taskPostProcessor(resp.Tasks)
65 > }
66
67 > return resp.Tasks, resp.NextPageToken, nil queue_immediate.go
68 }
69 }
70
71 > return &immediateQueue{ queue_immediate.go
72 > queueBase: newQueueBase(
73 > shard,
74 > category,
75 > paginationFnProvider,
76 > scheduler,
77 > rescheduler,
78 > factory,
79 > options,
80 > hostRateLimiter,
81 > NoopReaderCompletionFn,
82 > grouper,
83 > logger,
84 > metricsHandler,
85 > ),
86 >
87 > notifyCh: make(chan struct{}, 1),
88 > }
89 }
90
91 > func (p *immediateQueue) Start() { queue_immediate.go
92 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
93 return
94 }
95
96 > p.logger.Info("", tag.LifeCycleStarting) queue_immediate.go
97 > defer p.logger.Info("", tag.LifeCycleStarted)
98 >
99 > p.queueBase.Start()
100 >
101 > p.shutdownWG.Add(1)
102 > go p.processEventLoop()
103 >
104 > p.notify()
105 }
106
107 > func (p *immediateQueue) Stop() { queue_immediate.go
108 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
109 return
110 }
111
112 > p.logger.Info("", tag.LifeCycleStopping) queue_immediate.go
113 > defer p.logger.Info("", tag.LifeCycleStopped)
114 >
115 > close(p.shutdownCh)
116 >
117 > if success := common.AwaitWaitGroup(&p.shutdownWG, time.Minute); !success {
118 p.logger.Warn("", tag.LifeCycleStopTimedout)
119 }
120
121 > p.queueBase.Stop() queue_immediate.go
122 }
123
124 > func (p *immediateQueue) NotifyNewTasks(tasks []tasks.Task) { queue_immediate.go
125 > if len(tasks) == 0 {
126 return
127 }
128
129 > p.notify() queue_immediate.go
130 }
131
132 > func (p *immediateQueue) processEventLoop() { queue_immediate.go
133 > defer p.shutdownWG.Done()
134 >
135 > pollTimer := time.NewTimer(backoff.Jitter(
136 > p.options.MaxPollInterval(),
137 > p.options.MaxPollIntervalJitterCoefficient(),
138 > ))
139 > defer pollTimer.Stop()
140 >
141 > for {
142 > select {
143 case <-p.shutdownCh:
144 return
145 > default: queue_immediate.go
146 }
147
148 > select { queue_immediate.go
149 > case <-p.shutdownCh: queue_immediate.go
150 > return
151 > case <-p.notifyCh: queue_immediate.go
152 > p.processNewRange()
153 case <-pollTimer.C:
154 p.processPollTimer(pollTimer)
go.temporal.io/server/common/persistence/sql/factory.go 81 covered LOC · 28 ranges

Open complete file

50 metricsHandler metrics.Handler,
51 serializer serialization.Serializer,
52 > ) *Factory { factory.go
53 > return &Factory{
54 > cfg: cfg,
55 > clusterName: clusterName,
56 > logger: logger,
57 > serializer: serializer,
58 > mainDBConn: NewRefCountedDBConn(sqlplugin.DbKindMain, &cfg, r, logger, metricsHandler),
59 > }
60 > }
61
62 // GetDB return a new SQL DB connection
70
71 // NewTaskStore returns a new task store
72 > func (f *Factory) NewTaskStore() (p.TaskStore, error) { factory.go
73 > conn, err := f.mainDBConn.Get()
74 > if err != nil {
75 return nil, err
76 }
77 > return newTaskPersistence(conn, f.cfg.TaskScanPartitions, f.logger, false, f.serializer) factory.go
78 }
79
80 // NewFairTaskStore returns a new task store
81 > func (f *Factory) NewFairTaskStore() (p.TaskStore, error) { factory.go
82 > conn, err := f.mainDBConn.Get()
83 > if err != nil {
84 return nil, err
85 }
86 > return newTaskPersistence(conn, f.cfg.TaskScanPartitions, f.logger, true, f.serializer) factory.go
87 }
88
89 // NewShardStore returns a new shard store
90 > func (f *Factory) NewShardStore() (p.ShardStore, error) { factory.go
91 > conn, err := f.mainDBConn.Get()
92 > if err != nil {
93 return nil, err
94 }
95 > return newShardPersistence(conn, f.clusterName, f.logger, f.serializer) factory.go
96 }
97
98 // NewMetadataStore returns a new metadata store
99 > func (f *Factory) NewMetadataStore() (p.MetadataStore, error) { factory.go
100 > conn, err := f.mainDBConn.Get()
101 > if err != nil {
102 return nil, err
103 }
104 > return newMetadataPersistenceV2(conn, f.clusterName, f.logger, f.serializer) factory.go
105 }
106
107 // NewClusterMetadataStore returns a new ClusterMetadata store
108 > func (f *Factory) NewClusterMetadataStore() (p.ClusterMetadataStore, error) { factory.go
109 > conn, err := f.mainDBConn.Get()
110 > if err != nil {
111 return nil, err
112 }
113 > return newClusterMetadataPersistence(conn, f.logger, f.serializer) factory.go
114 }
115
116 // NewExecutionStore returns a new ExecutionStore
117 > func (f *Factory) NewExecutionStore() (p.ExecutionStore, error) { factory.go
118 > conn, err := f.mainDBConn.Get()
119 > if err != nil {
120 return nil, err
121 }
122 > return NewSQLExecutionStore(conn, f.logger, f.serializer) factory.go
123 }
124
125 // NewQueue returns a new queue backed by sql
126 > func (f *Factory) NewQueue(queueType p.QueueType) (p.Queue, error) { factory.go
127 > conn, err := f.mainDBConn.Get()
128 > if err != nil {
129 return nil, err
130 }
131
132 > return newQueue(conn, f.logger, queueType, f.serializer) factory.go
133 }
134
135 // NewQueueV2 returns a new data-access object for queues and messages.
136 > func (f *Factory) NewQueueV2() (p.QueueV2, error) { factory.go
137 > conn, err := f.mainDBConn.Get()
138 > if err != nil {
139 return nil, err
140 }
141 > return NewQueueV2(conn, f.logger, f.serializer), nil factory.go
142 }
143
144 // NewNexusEndpointStore returns a new NexusEndpointStore
145 > func (f *Factory) NewNexusEndpointStore() (p.NexusEndpointStore, error) { factory.go
146 > conn, err := f.mainDBConn.Get()
147 > if err != nil {
148 return nil, err
149 }
150 > return NewSqlNexusEndpointStore(conn, f.logger, f.serializer) factory.go
151 }
152
153 // Close closes the factory
154 > func (f *Factory) Close() { factory.go
155 > f.mainDBConn.ForceClose()
156 > }
157
158 // NewRefCountedDBConn returns a logical mysql connection that
166 logger log.Logger,
167 metricsHandler metrics.Handler,
168 > ) DbConn { factory.go
169 > return DbConn{
170 > dbKind: dbKind,
171 > cfg: cfg,
172 > resolver: r,
173 > metrics: metricsHandler,
174 > logger: logger,
175 > }
176 > }
177
178 // Get returns a db connection and increments a reference count.
179 // This method will create a new connection, if an existing connection
180 // does not exist
181 > func (c *DbConn) Get() (sqlplugin.DB, error) { factory.go
182 > c.Lock()
183 > defer c.Unlock()
184 > if c.refCnt == 0 {
185 > conn, err := NewSQLDB(c.dbKind, c.cfg, c.resolver, c.logger, c.metrics)
186 > if err != nil {
187 return nil, err
188 }
189 > c.DB = conn factory.go
190 }
191 > c.refCnt++ factory.go
192 > return c, nil
193 }
194
195 // ForceClose ignores reference counts and shutsdown the underlying connection pool
196 > func (c *DbConn) ForceClose() { factory.go
197 > c.Lock()
198 > defer c.Unlock()
199 > if c.DB != nil {
200 > err := c.DB.Close()
201 > if err != nil {
202 fmt.Println("failed to close database connection, may leak some connection", err)
203 }
204 }
205 > c.refCnt = 0 factory.go
206 }
207
208 // Close closes the underlying connection if the reference count becomes zero
209 > func (c *DbConn) Close() error { factory.go
210 > c.Lock()
211 > defer c.Unlock()
212 > c.refCnt--
213 > if c.refCnt == 0 {
214 > return c.DB.Close()
215 > }
216 > return nil factory.go
217 }
go.temporal.io/server/api/persistence/v1/cluster_metadata.pb.go 79 covered LOC · 17 ranges

Open complete file

47 }
48
49 > func (x *ClusterMetadata) Reset() { cluster_metadata.pb.go
50 > *x = ClusterMetadata{}
51 > mi := &file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes[0]
52 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
53 > ms.StoreMessageInfo(mi)
54 > }
55
56 func (x *ClusterMetadata) String() string {
60 func (*ClusterMetadata) ProtoMessage() {}
61
62 > func (x *ClusterMetadata) ProtoReflect() protoreflect.Message { cluster_metadata.pb.go
63 > mi := &file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes[0]
64 > if x != nil {
65 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) cluster_metadata.pb.go
66 > if ms.LoadMessageInfo() == nil {
67 > ms.StoreMessageInfo(mi)
68 > }
69 > return ms
70 }
71 return mi.MessageOf(x)
77 }
78
79 > func (x *ClusterMetadata) GetClusterName() string { cluster_metadata.pb.go
80 > if x != nil {
81 > return x.ClusterName
82 > }
83 return ""
84 }
85
86 > func (x *ClusterMetadata) GetHistoryShardCount() int32 { cluster_metadata.pb.go
87 > if x != nil {
88 > return x.HistoryShardCount
89 > }
90 return 0
91 }
92
93 > func (x *ClusterMetadata) GetClusterId() string { cluster_metadata.pb.go
94 > if x != nil {
95 > return x.ClusterId
96 > }
97 return ""
98 }
112 }
113
114 > func (x *ClusterMetadata) GetClusterAddress() string { cluster_metadata.pb.go
115 > if x != nil {
116 > return x.ClusterAddress
117 > }
118 return ""
119 }
120
121 > func (x *ClusterMetadata) GetHttpAddress() string { cluster_metadata.pb.go
122 > if x != nil {
123 > return x.HttpAddress
124 > }
125 return ""
126 }
133 }
134
135 > func (x *ClusterMetadata) GetInitialFailoverVersion() int64 { cluster_metadata.pb.go
136 > if x != nil {
137 > return x.InitialFailoverVersion
138 > }
139 return 0
140 }
147 }
148
149 > func (x *ClusterMetadata) GetIsConnectionEnabled() bool { cluster_metadata.pb.go
150 > if x != nil {
151 > return x.IsConnectionEnabled
152 > }
153 return false
154 }
161 }
162
163 > func (x *ClusterMetadata) GetTags() map[string]string { cluster_metadata.pb.go
164 > if x != nil {
165 > return x.Tags
166 > }
167 return nil
168 }
169
170 > func (x *ClusterMetadata) GetIsReplicationEnabled() bool { cluster_metadata.pb.go
171 > if x != nil {
172 > return x.IsReplicationEnabled
173 > }
174 return false
175 }
195 func (*IndexSearchAttributes) ProtoMessage() {}
196
197 > func (x *IndexSearchAttributes) ProtoReflect() protoreflect.Message { cluster_metadata.pb.go
198 > mi := &file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes[1]
199 > if x != nil {
200 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) cluster_metadata.pb.go
201 > if ms.LoadMessageInfo() == nil {
202 > ms.StoreMessageInfo(mi)
203 > }
204 > return ms
205 }
206 > return mi.MessageOf(x) cluster_metadata.pb.go
207 }
208
289 }
290
291 > func init() { file_temporal_server_api_persistence_v1_cluster_metadata_proto_init() } cluster_metadata.pb.go
292 > func file_temporal_server_api_persistence_v1_cluster_metadata_proto_init() {
293 > if File_temporal_server_api_persistence_v1_cluster_metadata_proto != nil {
294 return
295 }
296 > type x struct{} cluster_metadata.pb.go
297 > out := protoimpl.TypeBuilder{
298 > File: protoimpl.DescBuilder{
299 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
300 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_cluster_metadata_proto_rawDesc), len(file_temporal_server_api_persistence_v1_cluster_metadata_proto_rawDesc)),
301 > NumEnums: 0,
302 > NumMessages: 5,
303 > NumExtensions: 0,
304 > NumServices: 0,
305 > },
306 > GoTypes: file_temporal_server_api_persistence_v1_cluster_metadata_proto_goTypes,
307 > DependencyIndexes: file_temporal_server_api_persistence_v1_cluster_metadata_proto_depIdxs,
308 > MessageInfos: file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes,
309 > }.Build()
310 > File_temporal_server_api_persistence_v1_cluster_metadata_proto = out.File
311 > file_temporal_server_api_persistence_v1_cluster_metadata_proto_goTypes = nil
312 > file_temporal_server_api_persistence_v1_cluster_metadata_proto_depIdxs = nil
313 }
go.temporal.io/server/client/client_bean.go 79 covered LOC · 14 ranges

Open complete file

56
57 // NewClientBean provides a collection of clients
58 > func NewClientBean(factory Factory, clusterMetadata cluster.Metadata) (Bean, error) { client_bean.go
59 >
60 > historyClient, err := factory.NewHistoryClientWithTimeout(history.DefaultTimeout)
61 > if err != nil {
62 return nil, err
63 }
64
65 > adminClients := map[string]adminservice.AdminServiceClient{} client_bean.go
66 > frontendClients := map[string]frontendClient{}
67 >
68 > currentClusterName := clusterMetadata.GetCurrentClusterName()
69 > // Init local cluster client with membership info
70 > adminClient, err := factory.NewLocalAdminClientWithTimeout(
71 > admin.DefaultTimeout,
72 > admin.DefaultLargeTimeout,
73 > )
74 > if err != nil {
75 return nil, err
76 }
77 > conn, client, err := factory.NewLocalFrontendClientWithTimeout( client_bean.go
78 > frontend.DefaultTimeout,
79 > frontend.DefaultLongPollTimeout,
80 > )
81 > if err != nil {
82 return nil, err
83 }
84 > adminClients[currentClusterName] = adminClient client_bean.go
85 > frontendClients[currentClusterName] = frontendClient{
86 > connection: conn,
87 > WorkflowServiceClient: client,
88 > }
89 >
90 > bean := &clientBeanImpl{
91 > factory: factory,
92 > historyClient: historyClient,
93 > clusterMetadata: clusterMetadata,
94 > adminClients: adminClients,
95 > frontendClients: frontendClients,
96 > }
97 > bean.registerClientEviction()
98 > return bean, nil
99 }
100
101 > func (h *clientBeanImpl) registerClientEviction() { client_bean.go
102 > currentCluster := h.clusterMetadata.GetCurrentClusterName()
103 > h.clusterMetadata.RegisterMetadataChangeCallback(
104 > h,
105 > func(oldClusterMetadata map[string]*cluster.ClusterInformation, newClusterMetadata map[string]*cluster.ClusterInformation) {
106 > for clusterName := range newClusterMetadata {
107 > if clusterName == currentCluster {
108 > continue
109 }
110 h.adminClientsLock.Lock()
120 // Close releases the resources held by the bean's clients. See the Bean
121 // interface for details. It is safe to call more than once.
122 > func (h *clientBeanImpl) Close() { client_bean.go
123 > h.clusterMetadata.UnRegisterMetadataChangeCallback(h)
124 >
125 > // The history and matching client wrapper chains implement Stop();
126 > // stopping them releases their daemon goroutines and cached gRPC
127 > // connections.
128 > if s, ok := h.historyClient.(interface{ Stop() }); ok {
129 > s.Stop()
130 > }
131 > if mc := h.matchingClient.Load(); mc != nil {
132 > if s, ok := mc.(interface{ Stop() }); ok {
133 > s.Stop()
134 > }
135 }
136 }
137
138 > func (h *clientBeanImpl) GetHistoryClient() historyservice.HistoryServiceClient { client_bean.go
139 > return h.historyClient
140 > }
141
142 > func (h *clientBeanImpl) GetMatchingClient(namespaceIDToName NamespaceIDToNameFunc) (matchingservice.MatchingServiceClient, error) { client_bean.go
143 > if client := h.matchingClient.Load(); client != nil {
144 return client.(matchingservice.MatchingServiceClient), nil
145 }
146 > return h.lazyInitMatchingClient(namespaceIDToName) client_bean.go
147 }
148
149 > func (h *clientBeanImpl) GetFrontendClient() workflowservice.WorkflowServiceClient { client_bean.go
150 > return h.frontendClients[h.clusterMetadata.GetCurrentClusterName()]
151 > }
152
153 > func (h *clientBeanImpl) GetRemoteAdminClient(cluster string) (adminservice.AdminServiceClient, error) { client_bean.go
154 > h.adminClientsLock.RLock()
155 > client, ok := h.adminClients[cluster]
156 > h.adminClientsLock.RUnlock()
157 > if ok {
158 > return client, nil
159 > }
160
161 clusterInfo, clusterFound := h.clusterMetadata.GetAllClusterInfo()[cluster]
234 }
235
236 > func (h *clientBeanImpl) lazyInitMatchingClient(namespaceIDToName NamespaceIDToNameFunc) (matchingservice.MatchingServiceClient, error) { client_bean.go
237 > h.Lock()
238 > defer h.Unlock()
239 > if cached := h.matchingClient.Load(); cached != nil {
240 return cached.(matchingservice.MatchingServiceClient), nil
241 }
242 > client, err := h.factory.NewMatchingClientWithTimeout(namespaceIDToName, matching.DefaultTimeout, matching.DefaultLongPollTimeout) client_bean.go
243 > if err != nil {
244 return nil, err
245 }
246 > h.matchingClient.Store(client) client_bean.go
247 > return client, nil
248 }
go.temporal.io/server/service/history/service.go 78 covered LOC · 13 ranges

Open complete file

50 healthServer *health.Server,
51 chasmRegistry *chasm.Registry,
52 > ) *Service { service.go
53 > return &Service{
54 > server: server,
55 > handler: handler,
56 > visibilityManager: visibilityMgr,
57 > config: serviceConfig,
58 > logger: logger,
59 > grpcListener: grpcListener,
60 > membershipMonitor: membershipMonitor,
61 > metricsHandler: metricsHandler,
62 > healthServer: healthServer,
63 > chasmRegistry: chasmRegistry,
64 > }
65 > }
66
67 // Start starts the service
68 > func (s *Service) Start() { service.go
69 > s.logger.Info("history starting")
70 >
71 > metrics.RestartCount.With(s.metricsHandler).Record(1)
72 >
73 > s.handler.Start()
74 >
75 > historyservice.RegisterHistoryServiceServer(s.server, s.handler)
76 > healthpb.RegisterHealthServer(s.server, s.healthServer)
77 > s.chasmRegistry.RegisterServices(s.server)
78 >
79 > // start as NOT_SERVING, update to SERVING after initial shards acquired
80 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING)
81 > readinessCtx, readinessCancel := context.WithCancel(context.Background())
82 > s.readinessCancel = readinessCancel
83 > go func() {
84 > if s.handler.controller.InitialShardsAcquired(readinessCtx) == nil {
85 > // add a few seconds for stabilization
86 > if util.InterruptibleSleep(readinessCtx, 5*time.Second) == nil {
87 s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_SERVING)
88 }
90 }()
91
92 > reflection.Register(s.server) service.go
93 >
94 > go func() {
95 > s.logger.Info("Starting to serve on history listener")
96 > if err := s.server.Serve(s.grpcListener); err != nil {
97 s.logger.Fatal("Failed to serve on history listener", tag.Error(err))
98 }
101 // As soon as we join membership, other hosts will send requests for shards that we own,
102 // so we should try to start this after starting the gRPC server.
103 > go func() { service.go
104 > if delay := s.config.StartupMembershipJoinDelay(); delay > 0 {
105 // In some situations, like rolling upgrades of the history service,
106 // pausing before joining membership can help separate the shard movement
110 time.Sleep(delay)
111 }
112 > s.membershipMonitor.Start() service.go
113 }()
114 }
115
116 // Stop stops the service
117 > func (s *Service) Stop() { service.go
118 > s.readinessCancel()
119 >
120 > // remove self from membership ring and wait for traffic to drain
121 > var err error
122 > var waitTime time.Duration
123 > if align := s.config.AlignMembershipChange(); align > 0 {
124 propagation := s.membershipMonitor.ApproximateMaxPropagationTime()
125 asOf := util.NextAlignedTime(time.Now().Add(propagation), align)
126 s.logger.Info("ShutdownHandler: Evicting self from membership ring as of", tag.Timestamp(asOf))
127 waitTime, err = s.membershipMonitor.EvictSelfAt(asOf)
128 > } else { service.go
129 > s.logger.Info("ShutdownHandler: Evicting self from membership ring immediately")
130 > err = s.membershipMonitor.EvictSelf()
131 > }
132 > if err != nil {
133 s.logger.Error("ShutdownHandler: Failed to evict self from membership ring", tag.Error(err))
134 }
135 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING) service.go
136 >
137 > s.logger.Info("ShutdownHandler: Waiting for drain")
138 > if waitTime > 0 {
139 time.Sleep(
140 waitTime + // wait for membership change
142 s.config.ShardFinalizerTimeout(), // and then take this long to run a finalizer
143 )
144 > } else { service.go
145 > time.Sleep(s.config.ShutdownDrainDuration())
146 > }
147
148 > enableCloseInboundReplicationStreamOnShutdown := s.config.EnableCloseInboundReplicationStreamOnShutdown() service.go
149 > // When enabled, stop handler components (including the replication stream monitor) before
150 > // waiting for gRPC handlers to return. This signals inbound stream senders on the peer to
151 > // stop, allowing their handler goroutines to unblock and return cleanly before GracefulStop.
152 > // Without this, those goroutines block indefinitely and the gRPC server falls back to a
153 > // forceful Stop(), causing unclean H2 teardowns on the peer.
154 > // Guarded by feature flag so the ordering change can be reverted if needed.
155 > if enableCloseInboundReplicationStreamOnShutdown {
156 > s.logger.Info("ShutdownHandler: Initiating handler shutdown")
157 > s.handler.Stop()
158 > } else {
159 s.logger.Info("ShutdownHandler: Initiating shardController shutdown")
160 s.handler.controller.Stop()
162
163 // All grpc handlers should be cancelled now. Give them a little time to return.
164 > t := time.AfterFunc(2*time.Second, func() { service.go
165 s.logger.Info("ShutdownHandler: Drain time expired, stopping all traffic")
166 s.server.Stop()
167 })
168 > s.server.GracefulStop() service.go
169 > t.Stop()
170 > if !enableCloseInboundReplicationStreamOnShutdown {
171 s.handler.Stop()
172 }
173 > s.visibilityManager.Close() service.go
174 >
175 > s.logger.Info("history stopped")
176 }
go.temporal.io/server/service/history/queue_factory_base.go 77 covered LOC · 11 ranges

Open complete file

79 fx.Provide(
80 QueueSchedulerRateLimiterProvider,
81 > func(tqm persistence.HistoryTaskQueueManager) queues.QueueWriter { queue_factory_base.go
82 > return tqm
83 > },
84 queues.NewDLQWriter,
85 fx.Annotated{
129 outboundParams outboundQueueFactoryParams,
130 config *configs.Config,
131 > ) additionalQueueFactories { queue_factory_base.go
132 > factories := []QueueFactory{}
133 > if _, ok := registry.GetCategoryByID(tasks.CategoryIDArchival); ok {
134 factories = append(factories, NewArchivalQueueFactory(archivalParams))
135 }
136 > factories = append(factories, NewOutboundQueueFactory(outboundParams)) queue_factory_base.go
137 > return additionalQueueFactories{
138 > Factories: factories,
139 > }
140 }
141
146 timeSource clock.TimeSource,
147 logger log.SnTaggedLogger,
148 > ) (queues.SchedulerRateLimiter, error) { queue_factory_base.go
149 > return queues.NewPrioritySchedulerRateLimiter(
150 > calculator.NewLoggedNamespaceCalculator(
151 > shard.NewOwnershipAwareNamespaceQuotaCalculator(
152 > ownershipBasedQuotaScaler,
153 > serviceResolver,
154 > config.TaskSchedulerNamespaceMaxQPS,
155 > config.TaskSchedulerGlobalNamespaceMaxQPS,
156 > ),
157 > log.With(logger, tag.ComponentTaskScheduler, tag.ScopeNamespace),
158 > ).GetQuota,
159 > calculator.NewLoggedCalculator(
160 > shard.NewOwnershipAwareQuotaCalculator(
161 > ownershipBasedQuotaScaler,
162 > serviceResolver,
163 > config.TaskSchedulerMaxQPS,
164 > config.TaskSchedulerGlobalMaxQPS,
165 > ),
166 > log.With(logger, tag.ComponentTaskScheduler, tag.ScopeHost),
167 > ).GetQuota,
168 > // TODO: reuse persistence rate limit calculator in PersistenceRateLimitingParamsProvider
169 > shard.NewOwnershipAwareNamespaceQuotaCalculator(
170 > ownershipBasedQuotaScaler,
171 > serviceResolver,
172 > config.PersistenceNamespaceMaxQPS,
173 > config.PersistenceGlobalNamespaceMaxQPS,
174 > ).GetQuota,
175 > shard.NewOwnershipAwareQuotaCalculator(
176 > ownershipBasedQuotaScaler,
177 > serviceResolver,
178 > config.PersistenceMaxQPS,
179 > config.PersistenceGlobalMaxQPS,
180 > ).GetQuota,
181 > )
182 > }
183
184 func QueueFactoryLifetimeHooks(
185 params QueueFactoriesLifetimeHookParams,
187 > params.Lifecycle.Append(
188 > fx.Hook{
189 > OnStart: func(context.Context) error {
190 > for _, factory := range params.Factories { queue_factory_base.go
191 > factory.Start()
192 > }
193 > return nil
194 },
195 > OnStop: func(context.Context) error { queue_factory_base.go
196 > for _, factory := range params.Factories {
197 > factory.Stop()
198 > }
199 > return nil
200 },
201 },
203 }
204
205 > func (f *QueueFactoryBase) Start() { queue_factory_base.go
206 > if f.HostScheduler != nil {
207 > f.HostScheduler.Start()
208 > }
209 }
210
211 > func (f *QueueFactoryBase) Stop() { queue_factory_base.go
212 > if f.HostScheduler != nil {
213 > f.HostScheduler.Stop()
214 > }
215 }
216
219 persistenceMaxRPS dynamicconfig.IntPropertyFn,
220 persistenceMaxRPSRatio float64,
221 > ) quotas.RateFn { queue_factory_base.go
222 > // TODO: reuse persistence rate limit calculator in PersistenceRateLimitingParamsProvider
223 >
224 > return func() float64 {
225 > if maxPollHostRps := hostRPS(); maxPollHostRps > 0 {
226 return float64(maxPollHostRps)
227 }
228
229 > if pMaxRPS := persistenceMaxRPS(); pMaxRPS > 0 { queue_factory_base.go
230 > // ensure queue loading won't consume all persistence tokens
231 > // especially upon host restart when we need to perform a load
232 > // for all shards
233 > return float64(pMaxRPS) * persistenceMaxRPSRatio
234 > }
235
236 // persistenceMaxQPS=0 means "unlimited" — use a high default to avoid
go.temporal.io/server/service/worker/deletenamespace/fx.go 77 covered LOC · 10 ranges

Open complete file

57 func newComponent(
58 params componentParams,
59 > ) workercommon.WorkerComponent { fx.go
60 > return &deleteNamespaceComponent{
61 > atWorkerCfg: dynamicconfig.WorkerDeleteNamespaceActivityLimits.Get(params.DynamicCollection)(),
62 > visibilityManager: params.VisibilityManager,
63 > metadataManager: params.MetadataManager,
64 > clusterMetadata: params.ClusterMetadata,
65 > nexusEndpointManager: params.NexusEndpointManager,
66 > historyClient: params.HistoryClient,
67 > metricsHandler: params.MetricsHandler,
68 > logger: params.Logger,
69 > protectedNamespaces: dynamicconfig.ProtectedNamespaces.Get(params.DynamicCollection),
70 > allowDeleteNamespaceIfNexusEndpointTarget: dynamicconfig.AllowDeleteNamespaceIfNexusEndpointTarget.Get(params.DynamicCollection),
71 > nexusEndpointListDefaultPageSize: dynamicconfig.NexusEndpointListDefaultPageSize.Get(params.DynamicCollection),
72 > deleteActivityRPS: dynamicconfig.DeleteNamespaceDeleteActivityRPS.Subscribe(params.DynamicCollection),
73 > useChasmDeleteExecution: dynamicconfig.DeleteNamespaceUseChasmDeleteExecution.Get(params.DynamicCollection),
74 > namespaceCacheRefreshInterval: dynamicconfig.NamespaceCacheRefreshInterval.Get(params.DynamicCollection),
75 > }
76 > }
77
78 > func (wc *deleteNamespaceComponent) RegisterWorkflow(registry sdkworker.Registry) { fx.go
79 > registry.RegisterWorkflowWithOptions(DeleteNamespaceWorkflow, workflow.RegisterOptions{Name: WorkflowName})
80 > registry.RegisterActivity(wc.deleteNamespaceLocalActivities())
81 >
82 > registry.RegisterWorkflowWithOptions(reclaimresources.ReclaimResourcesWorkflow, workflow.RegisterOptions{Name: reclaimresources.WorkflowName})
83 > registry.RegisterActivity(wc.reclaimResourcesLocalActivities())
84 >
85 > registry.RegisterWorkflowWithOptions(deleteexecutions.DeleteExecutionsWorkflow, workflow.RegisterOptions{Name: deleteexecutions.WorkflowName})
86 > registry.RegisterActivity(wc.deleteExecutionsLocalActivities())
87 > }
88
89 > func (wc *deleteNamespaceComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
90 > // use default worker
91 > return nil
92 > }
93
94 > func (wc *deleteNamespaceComponent) RegisterActivities(registry sdkworker.Registry) { fx.go
95 > registry.RegisterActivity(wc.reclaimResourcesActivities())
96 > registry.RegisterActivity(wc.deleteExecutionsActivities())
97 > }
98
99 > func (wc *deleteNamespaceComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
100 > return &workercommon.DedicatedWorkerOptions{
101 > TaskQueue: primitives.DeleteNamespaceActivityTQ,
102 > Options: sdkworker.Options{
103 > BackgroundActivityContext: headers.SetCallerType(context.Background(), headers.CallerTypePreemptable),
104 > MaxConcurrentActivityExecutionSize: wc.atWorkerCfg.MaxConcurrentActivityExecutionSize,
105 > TaskQueueActivitiesPerSecond: wc.atWorkerCfg.TaskQueueActivitiesPerSecond,
106 > WorkerActivitiesPerSecond: wc.atWorkerCfg.WorkerActivitiesPerSecond,
107 > MaxConcurrentActivityTaskPollers: wc.atWorkerCfg.MaxConcurrentActivityTaskPollers,
108 > },
109 > }
110 > }
111
112 > func (wc *deleteNamespaceComponent) deleteNamespaceLocalActivities() *localActivities { fx.go
113 > return newLocalActivities(
114 > wc.metadataManager,
115 > wc.clusterMetadata,
116 > wc.nexusEndpointManager,
117 > wc.logger,
118 > wc.protectedNamespaces,
119 > wc.allowDeleteNamespaceIfNexusEndpointTarget,
120 > wc.nexusEndpointListDefaultPageSize)
121 > }
122
123 > func (wc *deleteNamespaceComponent) reclaimResourcesActivities() *reclaimresources.Activities { fx.go
124 > return reclaimresources.NewActivities(wc.visibilityManager, wc.logger)
125 > }
126
127 > func (wc *deleteNamespaceComponent) reclaimResourcesLocalActivities() *reclaimresources.LocalActivities { fx.go
128 > return reclaimresources.NewLocalActivities(wc.visibilityManager, wc.metadataManager, wc.namespaceCacheRefreshInterval, wc.logger)
129 > }
130
131 > func (wc *deleteNamespaceComponent) deleteExecutionsActivities() *deleteexecutions.Activities { fx.go
132 > return deleteexecutions.NewActivities(
133 > wc.visibilityManager,
134 > wc.historyClient,
135 > wc.deleteActivityRPS,
136 > wc.useChasmDeleteExecution,
137 > wc.metricsHandler,
138 > wc.logger,
139 > )
140 > }
141
142 > func (wc *deleteNamespaceComponent) deleteExecutionsLocalActivities() *deleteexecutions.LocalActivities { fx.go
143 > return deleteexecutions.NewLocalActivities(wc.visibilityManager, wc.metricsHandler, wc.logger)
144 > }
go.temporal.io/server/common/persistence/sql/metadata.go 76 covered LOC · 27 ranges

Open complete file

25 logger log.Logger,
26 serializer serialization.Serializer,
27 > ) (persistence.MetadataStore, error) { metadata.go
28 > return &sqlMetadataManagerV2{
29 > SqlStore: NewSQLStore(db, logger, serializer),
30 > activeClusterName: currentClusterName,
31 > }, nil
32 > }
33
34 func (m *sqlMetadataManagerV2) CreateNamespace(
35 ctx context.Context,
36 request *persistence.InternalCreateNamespaceRequest,
37 > ) (*persistence.CreateNamespaceResponse, error) { metadata.go
38 > idBytes, err := primitives.ParseUUID(request.ID)
39 > if err != nil {
40 return nil, err
41 }
42
43 > var resp *persistence.CreateNamespaceResponse metadata.go
44 > err = m.txExecute(ctx, "CreateNamespace", func(tx sqlplugin.Tx) error {
45 > metadata, err := lockMetadata(ctx, tx)
46 > if err != nil {
47 return err
48 }
49 > if _, err := tx.InsertIntoNamespace(ctx, &sqlplugin.NamespaceRow{ metadata.go
50 > Name: request.Name,
51 > ID: idBytes,
52 > Data: request.Namespace.Data,
53 > DataEncoding: request.Namespace.EncodingType.String(),
54 > IsGlobal: request.IsGlobal,
55 > NotificationVersion: metadata.NotificationVersion,
56 > }); err != nil {
57 if m.DB.IsDupEntryError(err) {
58 return serviceerror.NewNamespaceAlreadyExistsf("name: %v", request.Name)
60 return err
61 }
62 > if err := updateMetadata(ctx, metadata.go
63 > tx,
64 > metadata.NotificationVersion,
65 > ); err != nil {
66 return err
67 }
68 > resp = &persistence.CreateNamespaceResponse{ID: request.ID} metadata.go
69 > return nil
70 })
71 > return resp, err metadata.go
72 }
73
75 ctx context.Context,
76 request *persistence.GetNamespaceRequest,
77 > ) (*persistence.InternalGetNamespaceResponse, error) { metadata.go
78 > idBytes, err := primitives.ParseUUID(request.ID)
79 > if err != nil {
80 return nil, err
81 }
82 > filter := sqlplugin.NamespaceFilter{} metadata.go
83 > switch {
84 case request.Name != "" && request.ID != "":
85 return nil, serviceerror.NewInvalidArgument("GetNamespace operation failed. Both ID and Name specified in request.")
86 > case request.Name != "": metadata.go
87 > filter.Name = &request.Name
88 case len(request.ID) != 0:
89 filter.ID = &idBytes
92 }
93
94 > rows, err := m.DB.SelectFromNamespace(ctx, filter) metadata.go
95 > if err != nil {
96 switch err {
97 case sql.ErrNoRows:
108 }
109
110 > response, err := m.namespaceRowToGetNamespaceResponse(&rows[0]) metadata.go
111 > if err != nil {
112 return nil, err
113 }
114
115 > return response, nil metadata.go
116 }
117
118 > func (m *sqlMetadataManagerV2) namespaceRowToGetNamespaceResponse(row *sqlplugin.NamespaceRow) (*persistence.InternalGetNamespaceResponse, error) { metadata.go
119 > return &persistence.InternalGetNamespaceResponse{
120 > Namespace: persistence.NewDataBlob(row.Data, row.DataEncoding),
121 > IsGlobal: row.IsGlobal,
122 > NotificationVersion: row.NotificationVersion,
123 > }, nil
124 > }
125
126 func (m *sqlMetadataManagerV2) UpdateNamespace(
224 ctx context.Context,
225 request *persistence.InternalListNamespacesRequest,
226 > ) (*persistence.InternalListNamespacesResponse, error) { metadata.go
227 > var pageToken *primitives.UUID
228 > if request.NextPageToken != nil {
229 token := primitives.UUID(request.NextPageToken)
230 pageToken = &token
231 }
232 > rows, err := m.DB.SelectFromNamespace(ctx, sqlplugin.NamespaceFilter{ metadata.go
233 > GreaterThanID: pageToken,
234 > PageSize: &request.PageSize,
235 > })
236 > if err != nil {
237 if err == sql.ErrNoRows {
238 return &persistence.InternalListNamespacesResponse{}, nil
241 }
242
243 > var namespaces []*persistence.InternalGetNamespaceResponse metadata.go
244 > for _, row := range rows {
245 > resp, err := m.namespaceRowToGetNamespaceResponse(&row) metadata.go
246 > if err != nil {
247 return nil, err
248 }
249 > namespaces = append(namespaces, resp) metadata.go
250 }
251
252 > resp := &persistence.InternalListNamespacesResponse{Namespaces: namespaces} metadata.go
253 > if len(rows) >= request.PageSize {
254 resp.NextPageToken = rows[len(rows)-1].ID
255 }
256
257 > return resp, nil metadata.go
258 }
259
262 tx sqlplugin.Tx,
263 oldNotificationVersion int64,
264 > ) error { metadata.go
265 > result, err := tx.UpdateNamespaceMetadata(ctx, &sqlplugin.NamespaceMetadataRow{
266 > NotificationVersion: oldNotificationVersion,
267 > })
268 > if err != nil {
269 return serviceerror.NewUnavailablef("Failed to update namespace metadata. Error: %v", err)
270 }
271
272 > rowsAffected, err := result.RowsAffected() metadata.go
273 > if err != nil {
274 return serviceerror.NewUnavailablef("Could not verify whether namespace metadata update occurred. Error: %v", err)
275 > } else if rowsAffected != 1 { metadata.go
276 return serviceerror.NewUnavailablef("Failed to update namespace metadata. <>1 rows affected. Error: %v", err)
277 }
278
279 > return nil metadata.go
280 }
281
283 ctx context.Context,
284 tx sqlplugin.Tx,
285 > ) (*sqlplugin.NamespaceMetadataRow, error) { metadata.go
286 > row, err := tx.LockNamespaceMetadata(ctx)
287 > if err != nil {
288 return nil, serviceerror.NewUnavailablef("Failed to lock namespace metadata. Error: %v", err)
289 }
290 > return row, nil metadata.go
291 }
go.temporal.io/server/common/tasks/interleaved_weighted_round_robin.go 75 covered LOC · 14 ranges

Open complete file

75 fifoScheduler Scheduler[T],
76 logger log.Logger,
77 > ) *InterleavedWeightedRoundRobinScheduler[T, K] { interleaved_weighted_round_robin.go
78 > iwrrChannels := atomic.Value{}
79 > iwrrChannels.Store(WeightedChannels[T]{})
80 >
81 > return &InterleavedWeightedRoundRobinScheduler[T, K]{
82 > status: common.DaemonStatusInitialized,
83 >
84 > ts: clock.NewRealTimeSource(),
85 > fifoScheduler: fifoScheduler,
86 > logger: logger,
87 >
88 > options: options,
89 >
90 > notifyChan: make(chan struct{}, 1),
91 > shutdownChan: make(chan struct{}),
92 >
93 > numInflightTask: 0,
94 > weightedChannels: make(map[K]*WeightedChannel[T]),
95 > iwrrChannels: iwrrChannels,
96 > }
97 > }
98
99 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) Start() { interleaved_weighted_round_robin.go
100 > if !atomic.CompareAndSwapInt32(
101 > &s.status,
102 > common.DaemonStatusInitialized,
103 > common.DaemonStatusStarted,
104 > ) {
105 return
106 }
107
108 > s.fifoScheduler.Start() interleaved_weighted_round_robin.go
109 >
110 > s.shutdownWG.Add(1)
111 > go s.eventLoop()
112 >
113 > s.shutdownWG.Add(1)
114 > go s.cleanupLoop()
115 >
116 > s.logger.Info("interleaved weighted round robin task scheduler started")
117 }
118
119 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) Stop() { interleaved_weighted_round_robin.go
120 > if !atomic.CompareAndSwapInt32(
121 > &s.status,
122 > common.DaemonStatusStarted,
123 > common.DaemonStatusStopped,
124 > ) {
125 return
126 }
127
128 > close(s.shutdownChan) interleaved_weighted_round_robin.go
129 >
130 > s.fifoScheduler.Stop()
131 >
132 > s.abortTasks()
133 >
134 > if success := common.AwaitWaitGroup(&s.shutdownWG, time.Minute); !success {
135 s.logger.Warn("interleaved weighted round robin task scheduler timed out on shutdown.")
136 }
137 > s.logger.Info("interleaved weighted round robin task scheduler stopped") interleaved_weighted_round_robin.go
138 }
139
177 }
178
179 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) eventLoop() { interleaved_weighted_round_robin.go
180 > defer s.shutdownWG.Done()
181 >
182 > for {
183 > select {
184 case <-s.notifyChan:
185 s.dispatchTasksWithWeight()
186 > case <-s.shutdownChan: interleaved_weighted_round_robin.go
187 > return
188 }
189 }
190 }
191
192 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) cleanupLoop() { interleaved_weighted_round_robin.go
193 > defer s.shutdownWG.Done()
194 > if s.options.InactiveChannelDeletionDelay == nil {
196 > }
197 > ch, _ := s.ts.NewTimer(s.options.InactiveChannelDeletionDelay()) interleaved_weighted_round_robin.go
198 > for {
199 > select {
200 case <-ch:
201 s.doCleanup()
202 ch, _ = s.ts.NewTimer(s.options.InactiveChannelDeletionDelay())
203 > case <-s.shutdownChan: interleaved_weighted_round_robin.go
204 > return
205 }
206 }
381 }
382
383 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) abortTasks() { interleaved_weighted_round_robin.go
384 > s.RLock()
385 > defer s.RUnlock()
386 >
387 > numTasks := int64(0)
388 > DrainLoop:
389 > for _, channel := range s.weightedChannels {
390 for {
391 select {
go.temporal.io/server/common/deadlock/deadlock.go 74 covered LOC · 11 ranges

Open complete file

64 }
65
66 > func NewDeadlockDetector(params params) *deadlockDetector { deadlock.go
67 > return &deadlockDetector{
68 > logger: params.Logger,
69 > healthServer: params.HealthServer,
70 > metricsHandler: params.MetricsHandler.WithTags(metrics.OperationTag(metrics.DeadlockDetectorScope)),
71 > config: config{
72 > DumpGoroutines: dynamicconfig.DeadlockDumpGoroutines.Get(params.Collection),
73 > FailHealthCheck: dynamicconfig.DeadlockFailHealthCheck.Get(params.Collection),
74 > AbortProcess: dynamicconfig.DeadlockAbortProcess.Get(params.Collection),
75 > Interval: dynamicconfig.DeadlockInterval.Get(params.Collection),
76 > MaxWorkersPerRoot: dynamicconfig.DeadlockMaxWorkersPerRoot.Get(params.Collection),
77 > },
78 > roots: params.Roots,
79 > }
80 > }
81
82 > func (dd *deadlockDetector) Start() error { deadlock.go
83 > for _, root := range dd.roots {
84 > pool := goro.NewAdaptivePool(
85 > clock.NewRealTimeSource(),
86 > 0,
87 > dd.config.MaxWorkersPerRoot(),
88 > 100*time.Millisecond,
89 > 10,
90 > )
91 > dd.pools = append(dd.pools, pool)
92 > loopCtx := &loopContext{
93 > dd: dd,
94 > root: root,
95 > p: pool,
96 > }
97 > dd.loops.Go(loopCtx.run)
98 > }
99 > return nil
100 }
101
102 > func (dd *deadlockDetector) Stop() error { deadlock.go
103 > for _, pool := range dd.pools {
104 > pool.Stop()
105 > }
106 > dd.loops.Cancel()
107 > // don't wait for workers to exit, they may be blocked
108 > return nil
109 }
110
151 }
152
153 > func (lc *loopContext) run(ctx context.Context) error { deadlock.go
154 > for {
155 > // ping blocks until it has passed all checks to a worker goroutine (using an
156 > // unbuffered channel).
157 > lc.ping(ctx, []pingable.Pingable{lc.root})
158 >
159 > timer := time.NewTimer(lc.dd.config.Interval())
160 > select {
161 case <-timer.C:
162 > case <-ctx.Done(): deadlock.go
163 > timer.Stop()
164 > return ctx.Err()
165 }
166 }
167 }
168
169 > func (lc *loopContext) ping(ctx context.Context, pingables []pingable.Pingable) { deadlock.go
170 > for _, pingable := range pingables {
171 > for _, check := range pingable.GetPingChecks() { deadlock.go
172 > lc.p.Do(func() { lc.check(ctx, check) })
173 }
174 }
175 }
176
177 > func (lc *loopContext) check(ctx context.Context, check pingable.Check) { deadlock.go
178 > lc.dd.logger.Debug("starting ping check", tag.Name(check.Name))
179 > startTime := time.Now().UTC()
180 > resolved := make(chan struct{})
181 >
182 > // Using AfterFunc is cheaper than creating another goroutine to be the waiter, since
183 > // we expect to always cancel it. If the go runtime is so messed up that it can't
184 > // create a goroutine, that's a bigger problem than we can handle.
185 > t := time.AfterFunc(check.Timeout, func() {
186 if ctx.Err() != nil {
187 // deadlock detector was stopped
197 lc.dd.adjustCurrent(-1)
198 })
199 > newPingables := check.Ping() deadlock.go
200 > t.Stop()
201 > if len(check.MetricsName) > 0 {
202 > lc.dd.metricsHandler.Timer(check.MetricsName).Record(time.Since(startTime)) deadlock.go
203 > }
204 > close(resolved) deadlock.go
205 >
206 > lc.dd.logger.Debug("ping check succeeded", tag.Name(check.Name))
207 >
208 > lc.ping(ctx, newPingables)
209 }
go.temporal.io/server/chasm/lib/scheduler/library.go 73 covered LOC · 5 ranges

Open complete file

40 BackfillerTaskHandler *BackfillerTaskHandler,
41 MigrateToWorkflowTaskHandler *SchedulerMigrateToWorkflowTaskHandler,
42 > ) *Library { library.go
43 > return &Library{
44 > config: config,
45 > handler: handler,
46 > SchedulerIdleTaskHandler: SchedulerIdleTaskHandler,
47 > SchedulerCallbacksTaskHandler: SchedulerCallbacksTaskHandler,
48 > GeneratorTaskHandler: GeneratorTaskHandler,
49 > InvokerExecuteTaskHandler: InvokerExecuteTaskHandler,
50 > InvokerProcessBufferTaskHandler: InvokerProcessBufferTaskHandler,
51 > BackfillerTaskHandler: BackfillerTaskHandler,
52 > MigrateToWorkflowTaskHandler: MigrateToWorkflowTaskHandler,
53 > }
54 > }
55
56 > func (l *Library) Name() string { library.go
57 > return chasm.SchedulerLibraryName
58 > }
59
60 > func (l *Library) Components() []*chasm.RegistrableComponent { library.go
61 > return []*chasm.RegistrableComponent{
62 > chasm.NewRegistrableComponent[*Scheduler](
63 > chasm.SchedulerComponentName,
64 > chasm.WithBusinessIDAlias("ScheduleId"),
65 > chasm.WithSearchAttributes(
66 > executionStatusSearchAttribute,
67 > scheduleNextActionTimeSearchAttribute,
68 > scheduleIdleCloseTimeSearchAttribute,
69 > scheduleRunningWorkflowCountSearchAttribute,
70 > scheduleBufferedStartsCountSearchAttribute,
71 > ),
72 > // Exposes Tweakables to scheduler components via the CHASM context
73 > // (see tweakablesFromContext).
74 > chasm.WithContextValues(l.config.contextValues()),
75 > ),
76 > chasm.NewRegistrableComponent[*Generator]("generator"),
77 > chasm.NewRegistrableComponent[*Invoker]("invoker"),
78 > chasm.NewRegistrableComponent[*Backfiller]("backfiller"),
79 > chasm.NewRegistrableComponent[*EventLog]("eventlog"),
80 > }
81 > }
82
83 > func (l *Library) Tasks() []*chasm.RegistrableTask { library.go
84 > return []*chasm.RegistrableTask{
85 > chasm.NewRegistrablePureTask(
86 > "idle",
87 > l.SchedulerIdleTaskHandler,
88 > ),
89 > chasm.NewRegistrableSideEffectTask(
90 > "callbacks",
91 > l.SchedulerCallbacksTaskHandler,
92 > ),
93 > chasm.NewRegistrablePureTask(
94 > "generate",
95 > l.GeneratorTaskHandler,
96 > ),
97 > chasm.NewRegistrableSideEffectTask(
98 > "execute",
99 > l.InvokerExecuteTaskHandler,
100 > ),
101 > chasm.NewRegistrablePureTask(
102 > "processBuffer",
103 > l.InvokerProcessBufferTaskHandler,
104 > ),
105 > chasm.NewRegistrablePureTask(
106 > "backfill",
107 > l.BackfillerTaskHandler,
108 > ),
109 > chasm.NewRegistrableSideEffectTask(
110 > "migrateToWorkflow",
111 > l.MigrateToWorkflowTaskHandler,
112 > ),
113 > }
114 > }
115
116 > func (l *Library) RegisterServices(server *grpc.Server) { library.go
117 > server.RegisterService(&schedulerpb.SchedulerService_ServiceDesc, l.handler)
118 > }
go.temporal.io/server/common/rpc/interceptor/telemetry.go 73 covered LOC · 19 ranges

Open complete file

101 logAllReqErrors dynamicconfig.BoolPropertyFnWithNamespaceFilter,
102 requestErrorHandler ErrorHandler,
103 > ) *TelemetryInterceptor { telemetry.go
104 > return &TelemetryInterceptor{
105 > namespaceRegistry: namespaceRegistry,
106 > metricsHandler: metricsHandler,
107 > logger: logger,
108 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
109 > logAllReqErrors: logAllReqErrors,
110 > requestErrorHandler: requestErrorHandler,
111 > }
112 > }
113
114 // telemetryUnaryOverrideOperationTag is used to override scope used for reporting a metric.
115 // Ideally this method should never be used.
116 > func telemetryUnaryOverrideOperationTag(fullName, operation string, req any) string { telemetry.go
117 > if strings.HasPrefix(fullName, api.WorkflowServicePrefix) {
118 > // GetWorkflowExecutionHistory method handles both long poll and regular calls. telemetry.go
119 > // Current plan is to eventually split GetWorkflowExecutionHistory into two APIs,
120 > // remove this "if" case when that is done.
121 > if operation == metrics.FrontendGetWorkflowExecutionHistoryScope {
122 if request, ok := req.(*workflowservice.GetWorkflowExecutionHistoryRequest); ok {
123 if request.GetWaitNewEvent() {
126 }
127 }
128 > return operation telemetry.go
129 } else if strings.HasPrefix(fullName, api.HistoryServicePrefix) {
130 // Special handling for Nexus operations to include service and operation in metric tag since the API is generic for all Nexus operations.
168 info *grpc.UnaryServerInfo,
169 handler grpc.UnaryHandler,
170 > ) (any, error) { telemetry.go
171 > methodName := api.MethodName(info.FullMethod)
172 > nsName := MustGetNamespaceName(ti.namespaceRegistry, req)
173 >
174 > metricsHandler, logTags := ti.unaryMetricsHandlerLogTags(req, info.FullMethod, methodName, nsName)
175 >
176 > ctx = AddTelemetryContext(ctx, metricsHandler)
177 > metrics.ServiceRequests.With(metricsHandler).Record(1)
178 >
179 > startTime := time.Now().UTC()
180 > defer func() {
181 > ti.RecordLatencyMetrics(ctx, startTime, metricsHandler)
182 > }()
183
184 > resp, err := handler(ctx, req) telemetry.go
185 >
186 > if configs.IsAPIOperation(info.FullMethod) {
187 > metrics.OperationCounter.With(metricsHandler).Record( telemetry.go
188 > 1,
189 > metrics.TaskTypeTag(""), // Added to make tags consistent with history task executor.
190 > )
191 > }
192
193 > if err != nil { telemetry.go
194 ti.requestErrorHandler.HandleError(req, info.FullMethod, metricsHandler, logTags, err, nsName)
195 > } else { telemetry.go
196 > // emit action metrics only after successful calls
197 > ti.emitActionMetric(methodName, info.FullMethod, req, metricsHandler, resp)
198 > }
199
200 > return resp, err telemetry.go
201 }
202
203 > func AddTelemetryContext(ctx context.Context, metricsHandler metrics.Handler) context.Context { telemetry.go
204 > return context.WithValue(ctx, metricsCtxKey, metricsHandler)
205 > }
206
207 > func (ti *TelemetryInterceptor) RecordLatencyMetrics(ctx context.Context, startTime time.Time, metricsHandler metrics.Handler) { telemetry.go
208 > userLatencyDuration := time.Duration(0)
209 > if val, ok := metrics.ContextCounterGet(ctx, metrics.HistoryWorkflowExecutionCacheLatency.Name()); ok {
210 userLatencyDuration = time.Duration(val)
211 metrics.ServiceLatencyUserLatency.With(metricsHandler).Record(userLatencyDuration)
212 }
213
214 > latency := time.Since(startTime) telemetry.go
215 > metrics.ServiceLatency.With(metricsHandler).Record(latency)
216 > noUserLatency := max(0, latency-userLatencyDuration)
217 > metrics.ServiceLatencyNoUserLatency.With(metricsHandler).Record(noUserLatency)
218 }
219
242 metricsHandler metrics.Handler,
243 result any,
244 > ) { telemetry.go
245 > if _, ok := grpcActions[methodName]; !ok || !strings.HasPrefix(fullName, api.WorkflowServicePrefix) {
246 > // grpcActions checks that methodName is the one that we care about, and we only care about WorkflowService. telemetry.go
247 > return
248 > }
249
250 switch methodName {
371 methodName string,
372 nsName namespace.Name,
373 > ) (metrics.Handler, []tag.Tag) { telemetry.go
374 > overridedMethodName := telemetryUnaryOverrideOperationTag(fullMethod, methodName, req)
375 >
376 > if nsName == "" {
377 > return baseMetricsHandler.WithTags(metrics.OperationTag(overridedMethodName), metrics.NamespaceUnknownTag()),
378 > []tag.Tag{tag.Operation(overridedMethodName)}
379 > }
380 return baseMetricsHandler.WithTags(metrics.OperationTag(overridedMethodName), metrics.NamespaceTag(nsName.String())),
381 []tag.Tag{tag.Operation(overridedMethodName), tag.WorkflowNamespace(nsName.String())}
385 fullMethod string,
386 methodName string,
387 > nsName namespace.Name) (metrics.Handler, []tag.Tag) { telemetry.go
388 > return CreateUnaryMetricsHandlerLogTags(ti.metricsHandler, req, fullMethod, methodName, nsName)
389 > }
390
391 func (ti *TelemetryInterceptor) streamMetricsHandlerLogTags(
403 ctx context.Context,
404 logger log.Logger,
405 > ) metrics.Handler { telemetry.go
406 > handler, ok := ctx.Value(metricsCtxKey).(metrics.Handler)
407 > if !ok {
408 logger.Error("unable to get metrics scope")
409 return metrics.NoopMetricsHandler
410 }
411 > return handler telemetry.go
412 }
go.temporal.io/server/service/frontend/admin_handler.go 71 covered LOC · 4 ranges

Open complete file

174 args NewAdminHandlerArgs,
175 namespaceDLQHandler nsreplication.DLQMessageHandler,
176 > ) *AdminHandler { admin_handler.go
177 > historyHealthChecker := NewHealthChecker(
178 > primitives.HistoryService,
179 > args.MembershipMonitor,
180 > args.Config.HistoryHostErrorPercentage,
181 > args.Config.HistoryHostSelfErrorProportion,
182 > func(ctx context.Context, hostAddress string) (*historyservice.DeepHealthCheckResponse, error) {
183 return args.HistoryClient.DeepHealthCheck(ctx, &historyservice.DeepHealthCheckRequest{HostAddress: hostAddress})
184 },
186 )
187
188 > return &AdminHandler{ admin_handler.go
189 > logger: args.Logger,
190 > status: common.DaemonStatusInitialized,
191 > numberOfHistoryShards: args.PersistenceConfig.NumHistoryShards,
192 > config: args.Config,
193 > namespaceDLQHandler: namespaceDLQHandler,
194 > eventSerializer: args.EventSerializer,
195 > visibilityMgr: args.visibilityMgr,
196 > persistenceExecutionName: args.PersistenceExecutionManager.GetName(),
197 > namespaceReplicationQueue: args.NamespaceReplicationQueue,
198 > taskManager: args.TaskManager,
199 > fairTaskManager: args.FairTaskManager,
200 > clusterMetadataManager: args.ClusterMetadataManager,
201 > persistenceMetadataManager: args.PersistenceMetadataManager,
202 > clientFactory: args.ClientFactory,
203 > clientBean: args.ClientBean,
204 > historyClient: args.HistoryClient,
205 > sdkClientFactory: args.sdkClientFactory,
206 > membershipMonitor: args.MembershipMonitor,
207 > hostInfoProvider: args.HostInfoProvider,
208 > metricsHandler: args.MetricsHandler,
209 > namespaceRegistry: args.NamespaceRegistry,
210 > saProvider: args.SaProvider,
211 > saManager: args.SaManager,
212 > saMapperProvider: args.SaMapperProvider,
213 > saValidator: searchattribute.NewValidator(
214 > args.SaProvider,
215 > args.SaMapperProvider,
216 > args.Config.SearchAttributesNumberOfKeysLimit,
217 > args.Config.SearchAttributesSizeOfValueLimit,
218 > args.Config.SearchAttributesTotalSizeLimit,
219 > args.visibilityMgr,
220 > visibility.AllowListForValidation(
221 > args.visibilityMgr.GetStoreNames(),
222 > args.Config.VisibilityAllowList,
223 > ),
224 > args.Config.SuppressErrorSetSystemSearchAttribute,
225 > args.MetricsHandler,
226 > args.Logger,
227 > ),
228 > clusterMetadata: args.ClusterMetadata,
229 > healthServer: args.HealthServer,
230 > historyHealthChecker: historyHealthChecker,
231 > taskCategoryRegistry: args.CategoryRegistry,
232 > matchingClient: args.matchingClient,
233 > chasmRegistry: args.ChasmRegistry,
234 > schedulerClient: args.SchedulerClient,
235 > }
236 }
237
238 // Start starts the handler
239 > func (adh *AdminHandler) Start() { admin_handler.go
240 > if atomic.CompareAndSwapInt32(
241 > &adh.status,
242 > common.DaemonStatusInitialized,
243 > common.DaemonStatusStarted,
244 > ) {
245 > adh.healthServer.SetServingStatus(AdminServiceName, grpchealthspb.HealthCheckResponse_SERVING)
246 > }
247 }
248
249 // Stop stops the handler
250 > func (adh *AdminHandler) Stop() { admin_handler.go
251 > if atomic.CompareAndSwapInt32(
252 > &adh.status,
253 > common.DaemonStatusStarted,
254 > common.DaemonStatusStopped,
255 > ) {
256 > adh.healthServer.SetServingStatus(AdminServiceName, grpchealthspb.HealthCheckResponse_NOT_SERVING)
257 > }
258 }
259
go.temporal.io/server/service/fx.go 71 covered LOC · 11 ranges

Open complete file

55
56 var PersistenceLazyLoadedServiceResolverModule = fx.Options(
57 > fx.Provide(func() PersistenceLazyLoadedServiceResolver { fx.go
58 > return PersistenceLazyLoadedServiceResolver{
59 > Value: &atomic.Value{},
60 > }
61 > }),
62 fx.Invoke(initPersistenceLazyLoadedServiceResolver),
63 )
68 serviceResolver membership.ServiceResolver,
69 lazyLoadedServiceResolver PersistenceLazyLoadedServiceResolver,
70 > ) { fx.go
71 > lazyLoadedServiceResolver.Store(serviceResolver)
72 > logger.Info("Initialized service resolver for persistence rate limiting", tag.Service(serviceName))
73 > }
74
75 func (p PersistenceLazyLoadedServiceResolver) AvailableMemberCount() int {
91 lazyLoadedServiceResolver PersistenceLazyLoadedServiceResolver,
92 logger log.Logger,
93 > ) PersistenceRateLimitingParams { fx.go
94 > hostCalculator := calculator.NewLoggedCalculator(
95 > calculator.ClusterAwareQuotaCalculator{
96 > MemberCounter: lazyLoadedServiceResolver,
97 > PerInstanceQuota: maxQps,
98 > GlobalQuota: globalMaxQps,
99 > },
100 > log.With(logger, tag.ComponentPersistence, tag.ScopeHost),
101 > )
102 > namespaceCalculator := calculator.NewLoggedNamespaceCalculator(
103 > calculator.ClusterAwareNamespaceQuotaCalculator{
104 > MemberCounter: lazyLoadedServiceResolver,
105 > PerInstanceQuota: namespaceMaxQps,
106 > GlobalQuota: globalNamespaceMaxQps,
107 > },
108 > log.With(logger, tag.ComponentPersistence, tag.ScopeNamespace),
109 > )
110 > return PersistenceRateLimitingParams{
111 > PersistenceMaxQps: func() int {
112 > return int(hostCalculator.GetQuota())
113 > },
114 PersistenceNamespaceMaxQps: func(namespace string) int {
115 return int(namespaceCalculator.GetQuota(namespace))
124 func GrpcServerOptionsProvider(
125 params GrpcServerOptionsParams,
126 > ) []grpc.ServerOption { fx.go
127 >
128 > grpcServerOptions, err := params.RPCFactory.GetInternodeGRPCServerOptions()
129 > if err != nil {
130 params.Logger.Fatal("creating gRPC server options failed", tag.Error(err))
131 }
132
133 > multiStats := rpc.MultiStatsHandler{} fx.go
134 > if params.TracingStatsHandler != nil {
135 multiStats = append(multiStats, params.TracingStatsHandler)
136 }
137 > if params.MetricsStatsHandler != nil { fx.go
138 > multiStats = append(multiStats, params.MetricsStatsHandler)
139 > }
140 > if len(multiStats) > 0 {
141 > grpcServerOptions = append(grpcServerOptions, grpc.StatsHandler(multiStats))
142 > }
143
144 > streamInterceptors := []grpc.StreamServerInterceptor{ fx.go
145 > params.TelemetryInterceptor.StreamIntercept,
146 > interceptor.CustomErrorStreamInterceptor,
147 > }
148 > if len(params.AdditionalStreamInterceptors) > 0 {
149 streamInterceptors = append(streamInterceptors, params.AdditionalStreamInterceptors...)
150 }
151
152 > return append( fx.go
153 > grpcServerOptions,
154 > grpc.ChainUnaryInterceptor(getUnaryInterceptors(params)...),
155 > grpc.ChainStreamInterceptor(streamInterceptors...),
156 > )
157 }
158
159 > func getUnaryInterceptors(params GrpcServerOptionsParams) []grpc.UnaryServerInterceptor { fx.go
160 > interceptors := []grpc.UnaryServerInterceptor{
161 > params.ServiceErrorInterceptor.Intercept,
162 > metrics.NewServerMetricsContextInjectorInterceptor(),
163 > metrics.NewServerMetricsTrailerPropagatorInterceptor(params.Logger),
164 > params.TelemetryInterceptor.UnaryIntercept,
165 > }
166 >
167 > interceptors = append(interceptors, params.AdditionalInterceptors...)
168 >
169 > if params.NamespaceRateLimitInterceptor != nil {
170 > interceptors = append(interceptors, params.NamespaceRateLimitInterceptor.Intercept)
171 > }
172
173 > interceptors = append(interceptors, params.RateLimitInterceptor.Intercept) fx.go
174 >
175 > if params.ContextMetadataInterceptor != nil {
176 > interceptors = append(interceptors, params.ContextMetadataInterceptor.Intercept)
177 > }
178
179 > return append(interceptors, params.RetryableInterceptor.Intercept) fx.go
180 }
go.temporal.io/server/chasm/registrable_component.go 69 covered LOC · 28 ranges

Open complete file

65 // If a registrable component is not detached by default, a component definition
66 // can specify its child as detached via ComponentFieldDetached() option.
67 > func WithDetached() RegistrableComponentOption { registrable_component.go
68 > return func(rc *RegistrableComponent) {
69 > rc.detached = true
70 > }
71 }
72
80 func WithBusinessIDAlias(
81 alias string,
82 > ) RegistrableComponentOption { registrable_component.go
83 > return func(rc *RegistrableComponent) {
84 > if rc.searchAttributesMapper == nil {
85 > rc.searchAttributesMapper = newVisibilitySearchAttributesMapper() registrable_component.go
86 > }
87 > if _, ok := rc.searchAttributesMapper.aliasToField[alias]; ok { registrable_component.go
88 //nolint:forbidigo
89 panic(fmt.Sprintf("registrable component validation error: business ID alias %q is already defined as a search attribute", alias))
90 }
91 > if _, ok := rc.searchAttributesMapper.systemAliasToField[alias]; ok { registrable_component.go
92 //nolint:forbidigo
93 panic(fmt.Sprintf("registrable component validation error: business ID alias %q is already defined as a system search attribute", alias))
94 }
95 > rc.searchAttributesMapper.systemAliasToField[alias] = sadefs.WorkflowID registrable_component.go
96 > rc.searchAttributesMapper.fieldToAlias[sadefs.WorkflowID] = alias
97 > rc.searchAttributesMapper.saTypeMap[sadefs.WorkflowID] = enumspb.INDEXED_VALUE_TYPE_KEYWORD
98 }
99 }
101 func WithSearchAttributes(
102 searchAttributes ...SearchAttribute,
103 > ) RegistrableComponentOption { registrable_component.go
104 > return func(rc *RegistrableComponent) {
105 > if len(searchAttributes) == 0 {
106 return
107 }
108
109 > if rc.searchAttributesMapper == nil { registrable_component.go
110 > rc.searchAttributesMapper = newVisibilitySearchAttributesMapper() registrable_component.go
111 > }
112
113 > for _, sa := range searchAttributes { registrable_component.go
114 > alias := sa.definition().alias
115 > field := sa.definition().field
116 > valueType := sa.definition().valueType
117 >
118 > // An identity-mapped system search attribute (alias == field, e.g. TaskQueue,
119 > // ExecutionTime) overrides that system column directly, so it is recorded only in
120 > // overriddenSystemFields; queries resolve via the system column.
121 > if field == alias && sadefs.IsSystem(field) {
122 > if !sadefs.IsChasmOverridableSystem(field) { registrable_component.go
123 //nolint:forbidigo
124 panic(fmt.Sprintf("registrable component validation error: system search attribute %q cannot be overridden by a CHASM component", field))
125 }
126 > if _, ok := rc.searchAttributesMapper.overriddenSystemFields[field]; ok { registrable_component.go
127 //nolint:forbidigo
128 panic(fmt.Sprintf("registrable component validation error: system search attribute override %q is already defined", field))
129 }
130 > rc.searchAttributesMapper.overriddenSystemFields[field] = valueType registrable_component.go
131 > continue
132 }
133
134 > if sadefs.IsChasmSystem(alias) { registrable_component.go
135 //nolint:forbidigo
136 panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is a CHASM system search attribute", alias))
137 }
138 > if !sadefs.IsSystem(alias) && sadefs.IsReserved(alias) { registrable_component.go
139 //nolint:forbidigo
140 panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is a reserved search attribute", alias))
141 }
142
143 > if _, ok := rc.searchAttributesMapper.systemAliasToField[alias]; ok { registrable_component.go
144 //nolint:forbidigo
145 panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is already defined as a system search attribute alias", alias))
146 }
147 > if _, ok := rc.searchAttributesMapper.aliasToField[alias]; ok { registrable_component.go
148 //nolint:forbidigo
149 panic(fmt.Sprintf("registrable component validation error: search attribute alias %q is already defined", alias))
150 }
151 > if _, ok := rc.searchAttributesMapper.fieldToAlias[field]; ok { registrable_component.go
152 //nolint:forbidigo
153 panic(fmt.Sprintf("registrable component validation error: search attribute field %q is already defined", field))
154 }
155
156 > rc.searchAttributesMapper.aliasToField[alias] = field registrable_component.go
157 > rc.searchAttributesMapper.fieldToAlias[field] = alias
158 > rc.searchAttributesMapper.saTypeMap[field] = valueType
159 }
160 }
173 func WithContextValues(
174 keyVals map[any]any,
175 > ) RegistrableComponentOption { registrable_component.go
176 > return func(rc *RegistrableComponent) {
177 > if rc.contextValues == nil {
178 > rc.contextValues = make(map[any]any, len(keyVals))
179 > }
180 > maps.Copy(rc.contextValues, keyVals)
181 }
182 }
184 func (rc *RegistrableComponent) registerToLibrary(
185 library namer,
186 > ) (string, uint32, error) { registrable_component.go
187 > if rc.library != nil {
188 return "", 0, fmt.Errorf("component %s is already registered in library %s", rc.componentType, rc.library.Name())
189 }
190
191 > rc.library = library registrable_component.go
192 > rc.fqn = FullyQualifiedName(rc.library.Name(), rc.componentType)
193 > rc.componentID = GenerateTypeID(rc.fqn)
194 > return rc.fqn, rc.componentID, nil
195 }
196
203 // The generated ID is used to uniquely identify components and tasks within the CHASM framework. The same FQN will
204 // always produce the same ID.
205 > func GenerateTypeID(fqn string) uint32 { registrable_component.go
206 > return farm.Fingerprint32([]byte(fqn))
207 > }
208
209 // hasBusinessIDAlias returns true if the component has a businessID alias configured
210 // via WithBusinessIDAlias option.
211 > func (rc *RegistrableComponent) hasBusinessIDAlias() bool { registrable_component.go
212 > if rc.searchAttributesMapper == nil {
213 return false
214 }
215 > _, ok := rc.searchAttributesMapper.fieldToAlias[sadefs.WorkflowID] registrable_component.go
216 > return ok
217 }
218
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/plugin.go 69 covered LOC · 25 ranges

Open complete file

43 }
44
45 > func init() { plugin.go
46 > sql.RegisterPlugin(PluginName, &plugin{
47 > queryConverter: &queryConverter{},
48 > connPool: newConnPool(),
49 > })
50 > }
51
52 func (p *plugin) GetVisibilityQueryConverter() sqlplugin.VisibilityQueryConverter {
61 logger log.Logger,
62 _ metrics.Handler,
63 > ) (sqlplugin.GenericDB, error) { plugin.go
64 > conn, err := p.connPool.Allocate(cfg, r, logger, p.createDBConnection)
65 > if err != nil {
66 return nil, err
67 }
68 > db := newDB(dbKind, cfg.DatabaseName, conn, nil, logger) plugin.go
69 > db.OnClose(func() { p.connPool.Close(cfg) }) // remove reference
70 > return db, nil
71 }
72
79 _ resolver.ServiceResolver,
80 logger log.Logger,
81 > ) (*sqlx.DB, error) { plugin.go
82 > dsn, err := buildDSN(cfg)
83 > if err != nil {
84 return nil, fmt.Errorf("error building DSN: %w", err)
85 }
86
87 > db, err := sqlx.Connect(goSQLDriverName, dsn) plugin.go
88 > if err != nil {
89 return nil, err
90 }
102 // respect the user's config values when set, otherwise default to 1 for
103 // backward compatibility and safety.
104 > walEnabled := strings.EqualFold(cfg.ConnectAttributes["journal_mode"], "wal") plugin.go
105 > if cfg.MaxConns > 0 {
106 if cfg.MaxConns > 1 && !walEnabled {
107 logger.Warn(
112 }
113 db.SetMaxOpenConns(cfg.MaxConns)
114 > } else { plugin.go
115 > db.SetMaxOpenConns(1)
116 > }
117 > if cfg.MaxIdleConns > 0 { plugin.go
118 db.SetMaxIdleConns(cfg.MaxIdleConns)
119 > } else { plugin.go
120 > db.SetMaxIdleConns(1) plugin.go
121 > }
122 > if cfg.MaxConnLifetime > 0 { plugin.go
123 db.SetConnMaxLifetime(cfg.MaxConnLifetime)
124 }
126 // closes. Set ConnMaxIdleTime to 0 (infinite) to prevent idle connections
127 // from being reaped, which would destroy the database.
128 > if cfg.ConnectAttributes["mode"] == "memory" { plugin.go
129 > db.SetConnMaxIdleTime(0) plugin.go
130 > }
131
132 // Maps struct names in CamelCase to snake without need for db struct tags.
133 > db.MapperFunc(strcase.ToSnake) plugin.go
134 >
135 > switch {
136 > case cfg.ConnectAttributes["mode"] == "memory": plugin.go
137 > // creates temporary DB overlay in order to configure database and schemas
138 > if err := p.setupSQLiteDatabase(cfg, db, logger); err != nil {
139 _ = db.Close()
140 return nil, err
147 }
148
149 > return db, nil plugin.go
150 }
151
152 > func (p *plugin) setupSQLiteDatabase(cfg *config.SQL, conn *sqlx.DB, logger log.Logger) error { plugin.go
153 > db := newDB(sqlplugin.DbKindUnknown, cfg.DatabaseName, conn, nil, logger)
154 > defer func() { _ = db.Close() }()
155
156 > err := db.CreateDatabase(cfg.DatabaseName) plugin.go
157 > if err != nil {
158 return err
159 }
160
161 // init tables
162 > return sqliteschema.SetupSchemaOnDB(db) plugin.go
163 }
164
165 > func buildDSN(cfg *config.SQL) (string, error) { plugin.go
166 > if cfg.ConnectAttributes == nil {
167 cfg.ConnectAttributes = make(map[string]string)
168 }
169 > vals, err := buildDSNAttr(cfg) plugin.go
170 > if err != nil {
171 return "", err
172 }
173 > dsn := fmt.Sprintf( plugin.go
174 > "file:%s?%v",
175 > cfg.DatabaseName,
176 > vals.Encode(),
177 > )
178 > return dsn, nil
179 }
180
181 > func buildDSNAttr(cfg *config.SQL) (url.Values, error) { plugin.go
182 > parameters := url.Values{}
183 >
184 > // sort ConnectAttributes to get a deterministic order
185 > keys := expmaps.Keys(cfg.ConnectAttributes)
186 > sort.Strings(keys)
187 >
188 > for _, k := range keys {
189 > key := strings.TrimSpace(k)
190 > value := strings.TrimSpace(cfg.ConnectAttributes[k])
191 > if parameters.Get(key) != "" {
192 return nil, fmt.Errorf("duplicate connection attr: %v:%v, %v:%v",
193 key,
197 }
198
199 > if _, isValidQueryParameter := queryParameters[key]; isValidQueryParameter { plugin.go
200 > parameters.Set(key, value)
201 > continue
202 }
203
206 }
207 // set time format
208 > parameters.Add("_time_format", "sqlite") plugin.go
209 > return parameters, nil
210 }
go.temporal.io/server/common/rpc/interceptor/namespace_validator.go 68 covered LOC · 29 ranges

Open complete file

95 maxNamespaceLength dynamicconfig.IntPropertyFn,
96 additionalAllowedMethodsDuringHandover []string,
97 > ) *NamespaceValidatorInterceptor { namespace_validator.go
98 > additional := make(map[string]struct{}, len(additionalAllowedMethodsDuringHandover))
99 > for _, m := range additionalAllowedMethodsDuringHandover {
100 additional[m] = struct{}{}
101 }
102 > return &NamespaceValidatorInterceptor{ namespace_validator.go
103 > namespaceRegistry: namespaceRegistry,
104 > tokenSerializer: tasktoken.NewSerializer(),
105 > enableTokenNamespaceEnforcement: enableTokenNamespaceEnforcement,
106 > additionalAllowedMethodsDuringHandover: additional,
107 > maxNamespaceLength: maxNamespaceLength,
108 > }
109 }
110
114 info *grpc.UnaryServerInfo,
115 handler grpc.UnaryHandler,
116 > ) (any, error) { namespace_validator.go
117 > err := ni.setNamespaceIfNotPresent(req)
118 > if err != nil {
119 return nil, err
120 }
121 > reqWithNamespace, hasNamespace := req.(NamespaceNameGetter) namespace_validator.go
122 > if hasNamespace {
123 > if err := ni.ValidateName(reqWithNamespace.GetNamespace()); err != nil {
124 return nil, err
125 }
126 }
127
128 > return handler(ctx, req) namespace_validator.go
129 }
130
131 // ValidateName validates a namespace name (currently only a max length check).
132 > func (ni *NamespaceValidatorInterceptor) ValidateName(ns string) error { namespace_validator.go
133 > if len(ns) > ni.maxNamespaceLength() {
134 return errNamespaceTooLong
135 }
136 > return nil namespace_validator.go
137 }
138
139 func (ni *NamespaceValidatorInterceptor) setNamespaceIfNotPresent(
140 req any,
141 > ) error { namespace_validator.go
142 > switch request := req.(type) {
143 > case NamespaceNameGetter:
144 > if request.GetNamespace() == "" {
145 namespaceEntry, err := ni.extractNamespaceFromTaskToken(req)
146 if err != nil {
205 info *grpc.UnaryServerInfo,
206 handler grpc.UnaryHandler,
207 > ) (any, error) { namespace_validator.go
208 > namespaceEntry, err := ni.extractNamespace(req)
209 > if err != nil {
210 return nil, err
211 }
212
213 > if err := ni.ValidateState(namespaceEntry, info.FullMethod, GetRoutingKeyFromContext(ctx).ID); err != nil { namespace_validator.go
214 return nil, err
215 }
216
217 > return handler(ctx, req) namespace_validator.go
218 }
219
224 // 4. Namespace from request match namespace from task token, if check is enabled with dynamic config.
225 // 5. Namespace is in correct state.
226 > func (ni *NamespaceValidatorInterceptor) ValidateState(namespaceEntry *namespace.Namespace, fullMethod string, businessID string) error { namespace_validator.go
227 > if err := ni.checkNamespaceState(namespaceEntry, fullMethod); err != nil {
228 return err
229 }
230 > return ni.checkReplicationState(namespaceEntry, fullMethod, businessID) namespace_validator.go
231 }
232
233 > func (ni *NamespaceValidatorInterceptor) extractNamespace(req any) (*namespace.Namespace, error) { namespace_validator.go
234 > // Token namespace has priority over request namespace. Check it first.
235 > tokenNamespaceEntry, tokenErr := ni.extractNamespaceFromTaskToken(req)
236 > if tokenErr != nil {
237 return nil, tokenErr
238 }
239
240 > requestNamespaceEntry, requestErr := ni.extractNamespaceFromRequest(req) namespace_validator.go
241 > // If namespace was extracted from token then it will be used.
242 > if requestErr != nil && tokenNamespaceEntry == nil {
243 return nil, requestErr
244 }
245
246 > err := ni.checkNamespaceMatch(requestNamespaceEntry, tokenNamespaceEntry) namespace_validator.go
247 > if err != nil {
248 return nil, err
249 }
250
251 // Use namespace from task token (if specified) and ignore namespace from request.
252 > if tokenNamespaceEntry != nil { namespace_validator.go
253 return tokenNamespaceEntry, nil
254 }
255
256 > return requestNamespaceEntry, nil namespace_validator.go
257 }
258
259 > func (ni *NamespaceValidatorInterceptor) extractNamespaceFromRequest(req any) (*namespace.Namespace, error) { namespace_validator.go
260 > reqWithNamespace, hasNamespace := req.(NamespaceNameGetter)
261 > if !hasNamespace {
262 > return nil, nil namespace_validator.go
263 > }
264 namespaceName := namespace.Name(reqWithNamespace.GetNamespace())
265
322 }
323
324 > func (ni *NamespaceValidatorInterceptor) extractNamespaceFromTaskToken(req any) (*namespace.Namespace, error) { namespace_validator.go
325 > reqWithTaskToken, hasTaskToken := req.(TaskTokenGetter)
326 > if !hasTaskToken {
327 > return nil, nil namespace_validator.go
328 > }
329 taskTokenBytes := reqWithTaskToken.GetTaskToken()
330 if len(taskTokenBytes) == 0 {
353 }
354
355 > func (ni *NamespaceValidatorInterceptor) checkNamespaceMatch(requestNamespace *namespace.Namespace, tokenNamespace *namespace.Namespace) error { namespace_validator.go
356 > if tokenNamespace == nil || requestNamespace == nil || !ni.enableTokenNamespaceEnforcement() {
357 > return nil
358 > }
359
360 if requestNamespace.ID() != tokenNamespace.ID() {
364 }
365
366 > func (ni *NamespaceValidatorInterceptor) checkNamespaceState(namespaceEntry *namespace.Namespace, fullMethod string) error { namespace_validator.go
367 > if namespaceEntry == nil {
368 > return nil namespace_validator.go
369 > }
370
371 allowedStates, allowedStatesPerAPIDefined := allowedNamespaceStatesPerAPI[fullMethod]
386 }
387
388 > func (ni *NamespaceValidatorInterceptor) checkReplicationState(namespaceEntry *namespace.Namespace, fullMethod string, businessID string) error { namespace_validator.go
389 > if namespaceEntry == nil {
390 > return nil namespace_validator.go
391 > }
392 if namespaceEntry.ReplicationState(businessID) != enumspb.REPLICATION_STATE_HANDOVER {
393 return nil
go.temporal.io/server/service/history/shard/ownership.go 68 covered LOC · 17 ranges

Open complete file

44 logger log.Logger,
45 metricsHandler metrics.Handler,
46 > ) *ownership { ownership.go
47 > hostIdentity := hostInfoProvider.HostInfo().Identity()
48 > logger = log.With(logger, tag.ComponentShardController, tag.Address(hostIdentity))
49 > return &ownership{
50 > acquireCh: make(chan struct{}, 1),
51 > config: config,
52 > historyServiceResolver: historyServiceResolver,
53 > hostInfoProvider: hostInfoProvider,
54 > logger: logger,
55 > membershipUpdateCh: make(chan *membership.ChangedEvent, 1),
56 > metricsHandler: metricsHandler,
57 > }
58 > }
59
60 > func (o *ownership) start(controller *ControllerImpl) { ownership.go
61 > o.goros.Go(func(ctx context.Context) error {
62 > o.eventLoop(ctx)
63 > return nil
64 > })
65
66 > o.goros.Go(func(ctx context.Context) error { ownership.go
67 > o.acquireLoop(ctx, controller)
68 > return nil
69 > })
70
71 > if err := o.historyServiceResolver.AddListener( ownership.go
72 > shardControllerMembershipUpdateListenerName,
73 > o.membershipUpdateCh,
74 > ); err != nil {
75 o.logger.Fatal("Error adding listener", tag.Error(err))
76 }
77 }
78
79 > func (o *ownership) eventLoop(ctx context.Context) { ownership.go
80 > acquireTicker := time.NewTicker(o.config.AcquireShardInterval())
81 > defer acquireTicker.Stop()
82 >
83 > for {
84 > select {
85 > case <-ctx.Done(): ownership.go
86 > return
87 case <-acquireTicker.C:
88 o.scheduleAcquire()
89 > case changedEvent := <-o.membershipUpdateCh: ownership.go
90 > metrics.MembershipChangedCounter.With(o.metricsHandler).Record(1)
91 >
92 > o.logger.Info("", tag.ValueRingMembershipChangedEvent,
93 > tag.NumberProcessed(len(changedEvent.HostsAdded)),
94 > tag.NumberDeleted(len(changedEvent.HostsRemoved)),
95 > tag.NumberChanged(len(changedEvent.HostsChanged)),
96 > )
97 >
98 > o.scheduleAcquire()
99 }
100 }
101 }
102
103 > func (o *ownership) scheduleAcquire() { ownership.go
104 > select {
105 > case o.acquireCh <- struct{}{}:
106 default:
107 }
108 }
109
110 > func (o *ownership) acquireLoop(ctx context.Context, controller *ControllerImpl) { ownership.go
111 > for {
112 > select {
113 > case <-ctx.Done(): ownership.go
114 > return
115 > case <-o.acquireCh: ownership.go
116 > controller.acquireShards(ctx)
117 }
118 }
119 }
120
121 > func (o *ownership) stop() { ownership.go
122 > if err := o.historyServiceResolver.RemoveListener(
123 > shardControllerMembershipUpdateListenerName,
124 > ); err != nil {
125 o.logger.Error("Error removing membership update listener", tag.Error(err), tag.OperationFailed)
126 }
127
128 > o.goros.Cancel() ownership.go
129 > o.goros.Wait()
130 }
131
133 // controller. If membership lists another host as the owner, it returns a
134 // ShardOwnershipLost error with the correct owner.
135 > func (o *ownership) verifyOwnership(shardID int32) error { ownership.go
136 > ownerInfo, err := o.historyServiceResolver.Lookup(convert.Int32ToString(shardID))
137 > if err != nil {
138 > return err ownership.go
139 > }
140
141 > hostInfo := o.hostInfoProvider.HostInfo() ownership.go
142 > if ownerInfo.Identity() != hostInfo.Identity() {
143 return serviceerrors.NewShardOwnershipLost(ownerInfo.Identity(), hostInfo.GetAddress())
144 }
145
146 > return nil ownership.go
147 }
go.temporal.io/server/chasm/lib/activity/library.go 67 covered LOC · 6 ranges

Open complete file

44 config *Config,
45 namespaceRegistry namespace.Registry,
46 > ) *componentOnlyLibrary { library.go
47 > return &componentOnlyLibrary{
48 > config: config,
49 > namespaceRegistry: namespaceRegistry,
50 > }
51 > }
52
53 > func (l *componentOnlyLibrary) Name() string { library.go
54 > return libraryName
55 > }
56
57 > func (l *componentOnlyLibrary) Components() []*chasm.RegistrableComponent { library.go
58 > return []*chasm.RegistrableComponent{
59 > chasm.NewRegistrableComponent[*Activity](
60 > componentName,
61 > chasm.WithSearchAttributes(
62 > TypeSearchAttribute,
63 > StatusSearchAttribute,
64 > chasm.SearchAttributeTaskQueue,
65 > chasm.SearchAttributeExecutionTime,
66 > ),
67 > chasm.WithBusinessIDAlias("ActivityId"),
68 > chasm.WithContextValues(map[any]any{
69 > ctxKeyActivityContext: &activityContext{
70 > config: l.config,
71 > namespaceRegistry: l.namespaceRegistry,
72 > },
73 > }),
74 > ),
75 > }
76 > }
77
78 // NewNilLibrary creates a Library with all nil handlers. Useful for
104 config *Config,
105 namespaceRegistry namespace.Registry,
106 > ) *library { library.go
107 > return &library{
108 > componentOnlyLibrary: *newComponentOnlyLibrary(config, namespaceRegistry),
109 > handler: handler,
110 > activityDispatchTaskHandler: activityDispatchTaskHandler,
111 > scheduleToStartTimeoutTaskHandler: scheduleToStartTimeoutTaskHandler,
112 > scheduleToCloseTimeoutTaskHandler: scheduleToCloseTimeoutTaskHandler,
113 > startToCloseTimeoutTaskHandler: startToCloseTimeoutTaskHandler,
114 > heartbeatTimeoutTaskHandler: heartbeatTimeoutTaskHandler,
115 > }
116 > }
117
118 > func (l *library) RegisterServices(server *grpc.Server) { library.go
119 > server.RegisterService(&activitypb.ActivityService_ServiceDesc, l.handler)
120 > }
121
122 > func (l *library) Tasks() []*chasm.RegistrableTask { library.go
123 > return []*chasm.RegistrableTask{
124 > chasm.NewRegistrableSideEffectTask(
125 > "dispatch",
126 > l.activityDispatchTaskHandler,
127 > ),
128 > chasm.NewRegistrablePureTask(
129 > "scheduleToStartTimer",
130 > l.scheduleToStartTimeoutTaskHandler,
131 > ),
132 > chasm.NewRegistrablePureTask(
133 > "scheduleToCloseTimer",
134 > l.scheduleToCloseTimeoutTaskHandler,
135 > ),
136 > chasm.NewRegistrablePureTask(
137 > "startToCloseTimer",
138 > l.startToCloseTimeoutTaskHandler,
139 > ),
140 > chasm.NewRegistrablePureTask(
141 > "heartbeatTimer",
142 > l.heartbeatTimeoutTaskHandler,
143 > ),
144 > }
145 > }
go.temporal.io/server/common/metrics/runtime.go 66 covered LOC · 10 ranges

Open complete file

37 logger log.Logger,
38 instanceID string,
39 > ) *RuntimeMetricsReporter { runtime.go
40 > if len(instanceID) > 0 {
41 handler = handler.WithTags(StringTag(instance, instanceID))
42 }
43 > var memstats runtime.MemStats runtime.go
44 > runtime.ReadMemStats(&memstats)
45 >
46 > return &RuntimeMetricsReporter{
47 > handler: handler,
48 > reportInterval: reportInterval,
49 > logger: logger,
50 > lastNumGC: memstats.NumGC,
51 > quit: make(chan struct{}),
52 > buildTime: build.InfoData.GitTime,
53 > buildInfoHandler: handler.WithTags(
54 > StringTag(gitRevisionTag, build.InfoData.GitRevision),
55 > StringTag(buildDateTag, build.InfoData.GitTime.Format(time.RFC3339)),
56 > StringTag(buildPlatformTag, build.InfoData.GoArch),
57 > StringTag(goVersionTag, build.InfoData.GoVersion),
58 > StringTag(buildVersionTag, headers.ServerVersion),
59 > ),
60 > }
61 }
62
63 // report Sends runtime metrics to the local metrics collector.
64 > func (r *RuntimeMetricsReporter) report() { runtime.go
65 > var memStats runtime.MemStats
66 > runtime.ReadMemStats(&memStats)
67 >
68 > NumGoRoutinesGauge.With(r.handler).Record(float64(runtime.NumGoroutine()))
69 > GoMaxProcsGauge.With(r.handler).Record(float64(runtime.GOMAXPROCS(0)))
70 > MemoryAllocatedGauge.With(r.handler).Record(float64(memStats.Alloc))
71 > MemoryHeapGauge.With(r.handler).Record(float64(memStats.HeapAlloc))
72 > MemoryHeapObjectsGauge.With(r.handler).Record(float64(memStats.HeapObjects))
73 > MemoryHeapIdleGauge.With(r.handler).Record(float64(memStats.HeapIdle))
74 > MemoryHeapInuseGauge.With(r.handler).Record(float64(memStats.HeapInuse))
75 > MemoryHeapReleasedGauge.With(r.handler).Record(float64(memStats.HeapReleased))
76 > MemoryStackGauge.With(r.handler).Record(float64(memStats.StackInuse))
77 > MemoryMallocsGauge.With(r.handler).Record(float64(memStats.Mallocs))
78 > MemoryFreesGauge.With(r.handler).Record(float64(memStats.Frees))
79 >
80 > NumGCGauge.With(r.handler).Record(float64(memStats.NumGC))
81 > GcPauseNsTotal.With(r.handler).Record(float64(memStats.PauseTotalNs))
82 >
83 > // memStats.NumGC is a perpetually incrementing counter (unless it wraps at 2^32)
84 > num := memStats.NumGC
85 > lastNum := atomic.SwapUint32(&r.lastNumGC, num) // reset for the next iteration
86 > if delta := num - lastNum; delta > 0 {
87 > NumGCCounter.With(r.handler).Record(int64(delta))
88 > if delta > 255 {
89 // too many GCs happened, the timestamps buffer got wrapped around. Report only the last 256
90 lastNum = num - 256
91 }
92 > for i := lastNum; i != num; i++ { runtime.go
93 > pause := memStats.PauseNs[i%256]
94 > GcPauseMsTimer.With(r.handler).Record(time.Duration(pause))
95 > }
96 }
97
98 // report build info
99 > r.buildInfoHandler.Gauge(buildInfoMetricName).Record(1.0) runtime.go
100 > r.buildInfoHandler.Gauge(buildAgeMetricName).Record(float64(time.Since(r.buildTime)))
101 }
102
103 // Start Starts the reporter thread that periodically emits metrics.
104 > func (r *RuntimeMetricsReporter) Start() { runtime.go
105 > if !atomic.CompareAndSwapInt32(&r.started, 0, 1) {
106 return
107 }
108 > r.report() runtime.go
109 > go func() {
110 > ticker := time.NewTicker(r.reportInterval)
111 > for {
112 > select {
113 case <-ticker.C:
114 r.report()
115 > case <-r.quit: runtime.go
116 > ticker.Stop()
117 > return
118 }
119 }
120 }()
121 > r.logger.Info("RuntimeMetricsReporter started") runtime.go
122 }
123
124 // Stop Stops reporting of runtime metrics. The reporter cannot be started again after it's been stopped.
125 > func (r *RuntimeMetricsReporter) Stop() { runtime.go
126 > close(r.quit)
127 > r.logger.Info("RuntimeMetricsReporter stopped")
128 > }
go.temporal.io/server/schema/sqlite/setup.go 66 covered LOC · 15 ranges

Open complete file

47 //
48 // Note: this function may receive breaking changes or be removed in the future.
49 > func SetupSchemaOnDB(db sqlplugin.AdminDB) error { setup.go
50 > statements, err := p.LoadAndSplitQueryFromReaders([]io.Reader{bytes.NewBuffer(executionSchema)})
51 > if err != nil {
52 return fmt.Errorf("error loading execution schema: %w", err)
53 }
54
55 > for _, stmt := range statements { setup.go
56 > if err = db.Exec(stmt); err != nil {
57 return fmt.Errorf("error executing statement %q: %w", stmt, err)
58 }
59 }
60
61 > statements, err = p.LoadAndSplitQueryFromReaders([]io.Reader{bytes.NewBuffer(visibilitySchema)}) setup.go
62 > if err != nil {
63 return fmt.Errorf("error loading visibility schema: %w", err)
64 }
65
66 > for _, stmt := range statements { setup.go
67 > if err = db.Exec(stmt); err != nil {
68 return fmt.Errorf("error executing statement %q: %w", stmt, err)
69 }
70 }
71
72 > return nil setup.go
73 }
74
91 //
92 // Note: this function may receive breaking changes or be removed in the future.
93 > func CreateNamespaces(cfg *config.SQL, namespaces ...*NamespaceConfig) error { setup.go
94 > db, err := sql.NewSQLDB(sqlplugin.DbKindUnknown, cfg, resolver.NewNoopResolver(), log.NewNoopLogger(), metrics.NoopMetricsHandler)
95 > if err != nil {
96 return fmt.Errorf("unable to create SQLite admin DB: %w", err)
97 }
98 > defer func() { _ = db.Close() }() setup.go
99
100 > for _, ns := range namespaces { setup.go
101 > if err := createNamespaceIfNotExists(db, ns); err != nil {
102 return fmt.Errorf("error creating namespace %q: %w", ns.Detail.Info.Name, err)
103 }
104 }
105
106 > return nil setup.go
107 }
108
116 global bool,
117 customSearchAttributes map[string]enumspb.IndexedValueType,
118 > ) (*NamespaceConfig, error) { setup.go
119 > dbCustomSearchAttributes := sadefs.GetDBIndexSearchAttributes(nil).CustomSearchAttributes
120 > fieldToAliasMap := map[string]string{}
121 > for saName, saType := range customSearchAttributes {
122 var targetFieldName string
123 var cntUsed int
142 }
143
144 > detail := persistencespb.NamespaceDetail{ setup.go
145 > Info: &persistencespb.NamespaceInfo{
146 > Id: primitives.NewUUID().String(),
147 > State: enumspb.NAMESPACE_STATE_REGISTERED,
148 > Name: namespace,
149 > },
150 > Config: &persistencespb.NamespaceConfig{
151 > Retention: timestamp.DurationFromHours(24),
152 > HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
153 > VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
154 > CustomSearchAttributeAliases: fieldToAliasMap,
155 > },
156 > ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
157 > ActiveClusterName: activeClusterName,
158 > Clusters: []string{activeClusterName},
159 > },
160 > FailoverVersion: common.EmptyVersion,
161 > FailoverNotificationVersion: -1,
162 > }
163 > return &NamespaceConfig{
164 > Detail: &detail,
165 > IsGlobal: global,
166 > }, nil
167 }
168
169 > func createNamespaceIfNotExists(db sqlplugin.DB, namespace *NamespaceConfig) error { setup.go
170 > var (
171 > name = namespace.Detail.GetInfo().GetName()
172 > id = primitives.MustParseUUID(namespace.Detail.GetInfo().GetId())
173 > )
174 >
175 > // Return early if namespace already exists
176 > rows, err := db.SelectFromNamespace(context.Background(), sqlplugin.NamespaceFilter{
177 > Name: &name,
178 > })
179 > if err == nil && len(rows) > 0 {
180 return nil
181 }
182
183 > blob, err := serialization.NewSerializer().NamespaceDetailToBlob(namespace.Detail) setup.go
184 > if err != nil {
185 return err
186 }
187
188 > if _, err := db.InsertIntoNamespace(context.Background(), &sqlplugin.NamespaceRow{ setup.go
189 > ID: id,
190 > Name: name,
191 > Data: blob.GetData(),
192 > DataEncoding: blob.GetEncodingType().String(),
193 > IsGlobal: namespace.IsGlobal,
194 > NotificationVersion: 0,
195 > }); err != nil {
196 return err
197 }
198
199 > return nil setup.go
200 }
go.temporal.io/server/common/persistence/cluster_metadata_store.go 65 covered LOC · 22 ranges

Open complete file

37 currentClusterName string,
38 logger log.Logger,
39 > ) ClusterMetadataManager { cluster_metadata_store.go
40 > return &clusterMetadataManagerImpl{
41 > serializer: serializer,
42 > persistence: persistence,
43 > currentClusterName: currentClusterName,
44 > logger: logger,
45 > }
46 > }
47
48 func (m *clusterMetadataManagerImpl) GetName() string {
50 }
51
52 > func (m *clusterMetadataManagerImpl) Close() { cluster_metadata_store.go
53 > m.persistence.Close()
54 > }
55
56 func (m *clusterMetadataManagerImpl) GetClusterMembers(
57 ctx context.Context,
58 request *GetClusterMembersRequest,
59 > ) (*GetClusterMembersResponse, error) { cluster_metadata_store.go
60 > return m.persistence.GetClusterMembers(ctx, request)
61 > }
62
63 func (m *clusterMetadataManagerImpl) UpsertClusterMembership(
64 ctx context.Context,
65 request *UpsertClusterMembershipRequest,
66 > ) error { cluster_metadata_store.go
67 > if request.RecordExpiry.Seconds() < 1 {
68 return ErrInvalidMembershipExpiry
69 }
70 > if request.Role == All { cluster_metadata_store.go
71 return ErrIncompleteMembershipUpsert
72 }
73 > if request.RPCAddress == nil { cluster_metadata_store.go
74 return ErrIncompleteMembershipUpsert
75 }
76 > if request.RPCPort == 0 { cluster_metadata_store.go
77 return ErrIncompleteMembershipUpsert
78 }
79 > if request.SessionStart.IsZero() { cluster_metadata_store.go
80 return ErrIncompleteMembershipUpsert
81 }
82
83 > return m.persistence.UpsertClusterMembership(ctx, request) cluster_metadata_store.go
84 }
85
87 ctx context.Context,
88 request *PruneClusterMembershipRequest,
89 > ) error { cluster_metadata_store.go
90 > return m.persistence.PruneClusterMembership(ctx, request)
91 > }
92
93 func (m *clusterMetadataManagerImpl) ListClusterMetadata(
94 ctx context.Context,
95 request *ListClusterMetadataRequest,
96 > ) (*ListClusterMetadataResponse, error) { cluster_metadata_store.go
97 > resp, err := m.persistence.ListClusterMetadata(ctx, &InternalListClusterMetadataRequest{
98 > PageSize: request.PageSize,
99 > NextPageToken: request.NextPageToken,
100 > })
101 > if err != nil {
102 return nil, err
103 }
104
105 > clusterMetadata := make([]*GetClusterMetadataResponse, 0, len(resp.ClusterMetadata)) cluster_metadata_store.go
106 > for _, cm := range resp.ClusterMetadata {
107 > res, err := m.convertInternalGetClusterMetadataResponse(cm)
108 > if err != nil {
109 return nil, err
110 }
111 > clusterMetadata = append(clusterMetadata, res) cluster_metadata_store.go
112 }
113 > return &ListClusterMetadataResponse{ClusterMetadata: clusterMetadata, NextPageToken: resp.NextPageToken}, nil cluster_metadata_store.go
114 }
115
116 func (m *clusterMetadataManagerImpl) GetCurrentClusterMetadata(
117 ctx context.Context,
118 > ) (*GetClusterMetadataResponse, error) { cluster_metadata_store.go
119 > resp, err := m.persistence.GetClusterMetadata(ctx, &InternalGetClusterMetadataRequest{ClusterName: m.currentClusterName})
120 > if err != nil {
121 return nil, err
122 }
123
124 > mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata) cluster_metadata_store.go
125 > if err != nil {
126 return nil, err
127 }
128 > return &GetClusterMetadataResponse{ClusterMetadata: mcm, Version: resp.Version}, nil cluster_metadata_store.go
129 }
130
132 ctx context.Context,
133 request *GetClusterMetadataRequest,
134 > ) (*GetClusterMetadataResponse, error) { cluster_metadata_store.go
135 > resp, err := m.persistence.GetClusterMetadata(ctx, &InternalGetClusterMetadataRequest{ClusterName: request.ClusterName})
136 > if err != nil {
137 > return nil, err
138 > }
139
140 mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata)
148 ctx context.Context,
149 request *SaveClusterMetadataRequest,
150 > ) (bool, error) { cluster_metadata_store.go
151 > mcm, err := m.serializer.SerializeClusterMetadata(request.ClusterMetadata)
152 > if err != nil {
153 return false, err
154 }
155
156 > oldClusterMetadata, err := m.GetClusterMetadata(ctx, &GetClusterMetadataRequest{ClusterName: request.GetClusterName()}) cluster_metadata_store.go
157 > if _, isNotFound := err.(*serviceerror.NotFound); isNotFound {
158 > return m.persistence.SaveClusterMetadata(ctx, &InternalSaveClusterMetadataRequest{
159 > ClusterName: request.ClusterName,
160 > ClusterMetadata: mcm,
161 > Version: request.Version,
162 > })
163 > }
164 if err != nil {
165 return false, err
189 func (m *clusterMetadataManagerImpl) convertInternalGetClusterMetadataResponse(
190 resp *InternalGetClusterMetadataResponse,
191 > ) (*GetClusterMetadataResponse, error) { cluster_metadata_store.go
192 > mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata)
193 > if err != nil {
194 return nil, err
195 }
196
197 > return &GetClusterMetadataResponse{ cluster_metadata_store.go
198 > ClusterMetadata: mcm,
199 > Version: resp.Version,
200 > }, nil
201 }
202
go.temporal.io/server/service/history/queues/monitor.go 65 covered LOC · 9 ranges

Open complete file

87 timeSource clock.TimeSource,
88 options *MonitorOptions,
89 > ) *monitorImpl { monitor.go
90 > return &monitorImpl{
91 > readerStats: make(map[int64]readerStats),
92 > sliceStats: make(map[Slice]sliceStats),
93 > categoryType: categoryType,
94 > timeSource: timeSource,
95 > options: options,
96 > pendingAlerts: make(map[AlertType]struct{}),
97 > silencedAlerts: make(map[AlertType]time.Time),
98 > alertCh: make(chan *Alert, alertChSize),
99 > shutdownCh: make(chan struct{}),
100 > }
101 > }
102
103 > func (m *monitorImpl) GetTotalPendingTaskCount() int { monitor.go
104 > m.Lock()
105 > defer m.Unlock()
106 >
107 > return m.totalPendingTaskCount
108 > }
109
110 func (m *monitorImpl) GetSlicePendingTaskCount(slice Slice) int {
118 }
119
120 > func (m *monitorImpl) SetSlicePendingTaskCount(slice Slice, count int) { monitor.go
121 > m.Lock()
122 > defer m.Unlock()
123 >
124 > stats := m.sliceStats[slice]
125 > m.totalPendingTaskCount = m.totalPendingTaskCount - stats.pendingTaskCount + count
126 >
127 > stats.pendingTaskCount = count
128 > m.sliceStats[slice] = stats
129 >
130 > criticalTotalTasks := m.options.PendingTasksCriticalCount()
131 > if criticalTotalTasks > 0 && m.totalPendingTaskCount > criticalTotalTasks {
132 m.sendAlertLocked(&Alert{
133 AlertType: AlertTypeQueuePendingTaskCount,
211 }
212
213 > func (m *monitorImpl) SetSliceCount(readerID int64, count int) { monitor.go
214 > m.Lock()
215 > defer m.Unlock()
216 >
217 > stats := m.readerStats[readerID]
218 > m.totalSliceCount = m.totalSliceCount - stats.sliceCount + count
219 >
220 > stats.sliceCount = count
221 > m.readerStats[readerID] = stats
222 >
223 > criticalSliceCount := m.options.SliceCountCriticalThreshold()
224 > if criticalSliceCount > 0 && m.totalSliceCount > criticalSliceCount {
225 m.sendAlertLocked(&Alert{
226 AlertType: AlertTypeSliceCount,
246 }
247
248 > func (m *monitorImpl) RemoveReader(readerID int64) { monitor.go
249 > m.Lock()
250 > defer m.Unlock()
251 >
252 > stats, ok := m.readerStats[readerID]
253 > if !ok {
254 return
255 }
256
257 > m.totalSliceCount -= stats.sliceCount monitor.go
258 > delete(m.readerStats, readerID)
259 }
260
274 }
275
276 > func (m *monitorImpl) AlertCh() <-chan *Alert { monitor.go
277 > return m.alertCh
278 > }
279
280 > func (m *monitorImpl) Close() { monitor.go
281 > m.Lock()
282 > defer m.Unlock()
283 >
284 > close(m.shutdownCh)
285 >
286 > for {
287 > select {
288 case <-m.alertCh:
289 // drain alertCh
290 > default: monitor.go
291 > close(m.alertCh)
292 > return
293 }
294 }
go.temporal.io/server/chasm/lib/nexusoperation/library.go 64 covered LOC · 6 ranges

Open complete file

36 }
37
38 > func newComponentOnlyLibrary(dc *dynamicconfig.Collection) *componentOnlyLibrary { library.go
39 > return &componentOnlyLibrary{
40 > metricTagConfig: MetricTagConfiguration.Get(dc),
41 > }
42 > }
43
44 > func (l *componentOnlyLibrary) Name() string { library.go
45 > return libraryName
46 > }
47
48 > func (l *componentOnlyLibrary) Components() []*chasm.RegistrableComponent { library.go
49 > return []*chasm.RegistrableComponent{
50 > chasm.NewRegistrableComponent[*Operation](
51 > componentName,
52 > chasm.WithSearchAttributes(
53 > EndpointSearchAttribute,
54 > ServiceSearchAttribute,
55 > OperationSearchAttribute,
56 > RequestIDSearchAttribute,
57 > StatusSearchAttribute,
58 > ),
59 > chasm.WithBusinessIDAlias("OperationId"),
60 > chasm.WithContextValues(map[any]any{
61 > OperationContextKey: &OperationContext{
62 > MetricTagConfig: l.metricTagConfig,
63 > },
64 > }),
65 > ),
66 > chasm.NewRegistrableComponent[*Cancellation]("cancellation"),
67 > }
68 > }
69
70 type Library struct {
93 cancellationBackoffTaskHandler *cancellationBackoffTaskHandler,
94 dc *dynamicconfig.Collection,
95 > ) *Library { library.go
96 > return &Library{
97 > componentOnlyLibrary: *newComponentOnlyLibrary(dc),
98 > handler: handler,
99 > operationBackoffTaskHandler: operationBackoffTaskHandler,
100 > operationInvocationTaskHandler: operationInvocationTaskHandler,
101 > operationScheduleToCloseTimeoutTaskHandler: operationScheduleToCloseTimeoutTaskHandler,
102 > operationScheduleToStartTimeoutTaskHandler: operationScheduleToStartTimeoutTaskHandler,
103 > operationStartToCloseTimeoutTaskHandler: operationStartToCloseTimeoutTaskHandler,
104 > cancellationInvocationTaskHandler: cancellationInvocationTaskHandler,
105 > cancellationBackoffTaskHandler: cancellationBackoffTaskHandler,
106 > }
107 > }
108
109 > func (l *Library) Tasks() []*chasm.RegistrableTask { library.go
110 > return []*chasm.RegistrableTask{
111 > chasm.NewRegistrableSideEffectTask(
112 > "invocation",
113 > l.operationInvocationTaskHandler,
114 > chasm.WithTaskGroup(TaskGroupName),
115 > ),
116 > chasm.NewRegistrablePureTask("invocationBackoff", l.operationBackoffTaskHandler),
117 > chasm.NewRegistrablePureTask("scheduleToStartTimeout", l.operationScheduleToStartTimeoutTaskHandler),
118 > chasm.NewRegistrablePureTask("startToCloseTimeout", l.operationStartToCloseTimeoutTaskHandler),
119 > chasm.NewRegistrablePureTask("scheduleToCloseTimeout", l.operationScheduleToCloseTimeoutTaskHandler),
120 > chasm.NewRegistrableSideEffectTask(
121 > "cancellation",
122 > l.cancellationInvocationTaskHandler,
123 > chasm.WithTaskGroup(TaskGroupName),
124 > ),
125 > chasm.NewRegistrablePureTask("cancellationBackoff", l.cancellationBackoffTaskHandler),
126 > }
127 > }
128
129 > func (l *Library) RegisterServices(server *grpc.Server) { library.go
130 > server.RegisterService(&nexusoperationpb.NexusOperationService_ServiceDesc, l.handler)
131 > }
go.temporal.io/server/service/history/replication/task_processor_manager.go 64 covered LOC · 12 ranges

Open complete file

71 testHooks testhooks.TestHooks,
72 dlqWriter DLQWriter,
73 > ) *taskProcessorManagerImpl { task_processor_manager.go
74 > historyFetcher := eventhandler.NewHistoryPaginatedFetcher(shardContext.GetNamespaceRegistry(), clientBean, eventSerializer, shardContext.GetLogger())
75 > return &taskProcessorManagerImpl{
76 > config: config,
77 > deleteMgr: workflowDeleteManager,
78 > engine: engine,
79 > eventSerializer: eventSerializer,
80 > shard: shardContext,
81 > status: common.DaemonStatusInitialized,
82 > replicationTaskFetcherFactory: replicationTaskFetcherFactory,
83 > workflowCache: workflowCache,
84 > removeHistoryFetcher: historyFetcher,
85 > logger: shardContext.GetLogger(),
86 > metricsHandler: shardContext.GetMetricsHandler(),
87 > testHooks: testHooks,
88 > dlqWriter: dlqWriter,
89 >
90 > enableFetcher: !config.EnableReplicationStream(),
91 > taskProcessors: make(map[string][]TaskProcessor),
92 > taskExecutorProvider: taskExecutorProvider,
93 > taskPollerManager: newPollerManager(shardContext.GetShardID(), shardContext.GetClusterMetadata()),
94 > minTxAckedTaskID: persistence.EmptyQueueMessageID,
95 > shutdownChan: make(chan struct{}),
96 > }
97 > }
98
99 > func (r *taskProcessorManagerImpl) Start() { task_processor_manager.go
100 > if !atomic.CompareAndSwapInt32(
101 > &r.status,
102 > common.DaemonStatusInitialized,
103 > common.DaemonStatusStarted,
104 > ) {
105 return
106 }
107
108 // Listen to cluster metadata and dynamically update replication processor for remote clusters.
109 > if r.enableFetcher { task_processor_manager.go
110 r.listenToClusterMetadataChange()
111 }
112 > go r.completeReplicationTaskLoop() task_processor_manager.go
113 > go r.checkReplicationDLQEmptyLoop()
114 }
115
116 > func (r *taskProcessorManagerImpl) Stop() { task_processor_manager.go
117 > if !atomic.CompareAndSwapInt32(
118 > &r.status,
119 > common.DaemonStatusStarted,
120 > common.DaemonStatusStopped,
121 > ) {
122 return
123 }
124
125 > close(r.shutdownChan) task_processor_manager.go
126 >
127 > if r.enableFetcher {
128 r.shard.GetClusterMetadata().UnRegisterMetadataChangeCallback(r)
129 }
130 > r.taskProcessorLock.Lock() task_processor_manager.go
131 > for _, taskProcessors := range r.taskProcessors {
132 for _, processor := range taskProcessors {
133 processor.Stop()
134 }
135 }
136 > r.taskProcessorLock.Unlock() task_processor_manager.go
137 }
138
208 }
209
210 > func (r *taskProcessorManagerImpl) completeReplicationTaskLoop() { task_processor_manager.go
211 > shardID := r.shard.GetShardID()
212 > cleanupTimer := time.NewTimer(backoff.Jitter(
213 > r.config.ReplicationTaskProcessorCleanupInterval(shardID),
214 > r.config.ReplicationTaskProcessorCleanupJitterCoefficient(shardID),
215 > ))
216 > defer cleanupTimer.Stop()
217 > for {
218 > select {
219 case <-cleanupTimer.C:
220 if err := r.cleanupReplicationTasks(); err != nil {
229 r.config.ReplicationTaskProcessorCleanupJitterCoefficient(shardID),
230 ))
231 > case <-r.shutdownChan: task_processor_manager.go
232 > return
233 }
234 }
235 }
236
237 > func (r *taskProcessorManagerImpl) checkReplicationDLQEmptyLoop() { task_processor_manager.go
238 > for {
239 > timer := time.NewTimer(backoff.FullJitter(dlqSizeCheckInterval))
240 > select {
241 case <-timer.C:
242 if r.config.ReplicationEnableDLQMetrics() {
243 r.checkReplicationDLQSize()
244 }
245 > case <-r.shutdownChan: task_processor_manager.go
246 > timer.Stop()
247 > return
248 }
249 }
go.temporal.io/server/api/persistence/v1/namespaces.pb.go 62 covered LOC · 15 ranges

Open complete file

42 }
43
44 > func (x *NamespaceDetail) Reset() { namespaces.pb.go
45 > *x = NamespaceDetail{}
46 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[0]
47 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
48 > ms.StoreMessageInfo(mi)
49 > }
50
51 func (x *NamespaceDetail) String() string {
55 func (*NamespaceDetail) ProtoMessage() {}
56
57 > func (x *NamespaceDetail) ProtoReflect() protoreflect.Message { namespaces.pb.go
58 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[0]
59 > if x != nil {
60 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
61 > if ms.LoadMessageInfo() == nil {
62 > ms.StoreMessageInfo(mi)
63 > }
64 > return ms
65 }
66 return mi.MessageOf(x)
72 }
73
74 > func (x *NamespaceDetail) GetInfo() *NamespaceInfo { namespaces.pb.go
75 > if x != nil {
76 > return x.Info
77 > }
78 return nil
79 }
146 func (*NamespaceInfo) ProtoMessage() {}
147
148 > func (x *NamespaceInfo) ProtoReflect() protoreflect.Message { namespaces.pb.go
149 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[1]
150 > if x != nil {
151 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
152 if ms.LoadMessageInfo() == nil {
163 }
164
165 > func (x *NamespaceInfo) GetId() string { namespaces.pb.go
166 > if x != nil {
167 > return x.Id
168 > }
169 return ""
170 }
177 }
178
179 > func (x *NamespaceInfo) GetName() string { namespaces.pb.go
180 > if x != nil {
181 > return x.Name
182 > }
183 return ""
184 }
233 func (*NamespaceConfig) ProtoMessage() {}
234
235 > func (x *NamespaceConfig) ProtoReflect() protoreflect.Message { namespaces.pb.go
236 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[2]
237 > if x != nil {
238 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
239 if ms.LoadMessageInfo() == nil {
336 func (*NamespaceReplicationConfig) ProtoMessage() {}
337
338 > func (x *NamespaceReplicationConfig) ProtoReflect() protoreflect.Message { namespaces.pb.go
339 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[3]
340 > if x != nil {
341 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
342 if ms.LoadMessageInfo() == nil {
403 func (*FailoverStatus) ProtoMessage() {}
404
405 > func (x *FailoverStatus) ProtoReflect() protoreflect.Message { namespaces.pb.go
406 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[4]
407 > if x != nil {
408 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
409 if ms.LoadMessageInfo() == nil {
536 }
537
538 > func init() { file_temporal_server_api_persistence_v1_namespaces_proto_init() } namespaces.pb.go
539 > func file_temporal_server_api_persistence_v1_namespaces_proto_init() {
540 > if File_temporal_server_api_persistence_v1_namespaces_proto != nil {
541 return
542 }
543 > type x struct{} namespaces.pb.go
544 > out := protoimpl.TypeBuilder{
545 > File: protoimpl.DescBuilder{
546 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
547 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_namespaces_proto_rawDesc), len(file_temporal_server_api_persistence_v1_namespaces_proto_rawDesc)),
548 > NumEnums: 0,
549 > NumMessages: 8,
550 > NumExtensions: 0,
551 > NumServices: 0,
552 > },
553 > GoTypes: file_temporal_server_api_persistence_v1_namespaces_proto_goTypes,
554 > DependencyIndexes: file_temporal_server_api_persistence_v1_namespaces_proto_depIdxs,
555 > MessageInfos: file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes,
556 > }.Build()
557 > File_temporal_server_api_persistence_v1_namespaces_proto = out.File
558 > file_temporal_server_api_persistence_v1_namespaces_proto_goTypes = nil
559 > file_temporal_server_api_persistence_v1_namespaces_proto_depIdxs = nil
560 }
go.temporal.io/server/common/quotas/priority_rate_limiter_impl.go 62 covered LOC · 14 ranges

Open complete file

28 requestPriorityFn RequestPriorityFn,
29 prioritiesOrdered []int,
30 > ) RequestRateLimiter { priority_rate_limiter_impl.go
31 > rateLimiters := make(map[int]RequestRateLimiter)
32 > for _, priority := range prioritiesOrdered {
33 > if priority == OperatorPriority {
34 > rateLimiters[priority] = NewRequestRateLimiterAdapter(
35 > NewDynamicRateLimiter(
36 > NewOperatorRateBurst(rateBurstFn, operatorRPSRatio),
37 > defaultRefreshInterval,
38 > ),
39 > )
40 > } else {
41 > rateLimiters[priority] = NewRequestRateLimiterAdapter(
42 > NewDynamicRateLimiter(
43 > rateBurstFn,
44 > defaultRefreshInterval,
45 > ),
46 > )
47 > }
48 }
49 > return NewPriorityRateLimiter(requestPriorityFn, rateLimiters) priority_rate_limiter_impl.go
50 }
51
55 requestPriorityFn RequestPriorityFn,
56 priorityToRateLimiters map[int]RequestRateLimiter,
57 > ) *PriorityRateLimiterImpl { priority_rate_limiter_impl.go
58 > priorities := make([]int, 0, len(priorityToRateLimiters))
59 > for priority := range priorityToRateLimiters {
60 > priorities = append(priorities, priority)
61 > }
62 > slices.Sort(priorities)
63 > priorityToIndex := make(map[int]int, len(priorityToRateLimiters))
64 > rateLimiters := make([]RequestRateLimiter, 0, len(priorityToRateLimiters))
65 > for index, priority := range priorities {
66 > priorityToIndex[priority] = index
67 > rateLimiters = append(rateLimiters, priorityToRateLimiters[priority])
68 > }
69
70 > return &PriorityRateLimiterImpl{ priority_rate_limiter_impl.go
71 > requestPriorityFn: requestPriorityFn,
72 > priorityToRateLimiters: priorityToRateLimiters,
73 >
74 > priorityToIndex: priorityToIndex,
75 > rateLimiters: rateLimiters,
76 > }
77 }
78
97 now time.Time,
98 request Request,
99 > ) Reservation { priority_rate_limiter_impl.go
100 > decidingRateLimiter, consumeRateLimiters := p.getRateLimiters(request)
101 >
102 > decidingReservation := decidingRateLimiter.Reserve(now, request)
103 > if !decidingReservation.OK() {
104 return decidingReservation
105 }
106
107 > otherReservations := make([]Reservation, len(consumeRateLimiters)) priority_rate_limiter_impl.go
108 > for index, limiter := range consumeRateLimiters {
109 > otherReservations[index] = limiter.Reserve(now, request) priority_rate_limiter_impl.go
110 > }
111 > return NewPriorityReservation(decidingReservation, otherReservations) priority_rate_limiter_impl.go
112 }
113
155 func (p *PriorityRateLimiterImpl) getRateLimiters(
156 request Request,
157 > ) (RequestRateLimiter, []RequestRateLimiter) { priority_rate_limiter_impl.go
158 > priority := p.requestPriorityFn(request)
159 > if _, ok := p.priorityToRateLimiters[priority]; !ok {
160 panic("Request to priority & priority to rate limiter does not match")
161 }
162
163 > rateLimiterIndex := p.priorityToIndex[priority] priority_rate_limiter_impl.go
164 > return p.rateLimiters[rateLimiterIndex], p.rateLimiters[rateLimiterIndex+1:]
165 }
go.temporal.io/server/service/history/memory_scheduled_queue_factory.go 62 covered LOC · 5 ranges

Open complete file

55 func NewMemoryScheduledQueueFactory(
56 params memoryScheduledQueueFactoryParams,
57 > ) QueueFactory { memory_scheduled_queue_factory.go
58 > logger := log.With(params.Logger, tag.ComponentMemoryScheduledQueue)
59 > metricsHandler := params.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationMemoryScheduledQueueProcessorScope))
60 >
61 > hostScheduler := ctasks.NewFIFOScheduler[ctasks.Task](
62 > &ctasks.FIFOSchedulerOptions{
63 > QueueSize: 0, // Don't buffer tasks in scheduler. If all workers are busy memoryScheduledQueue reschedules tasks into itself.
64 > WorkerCount: params.Config.MemoryTimerProcessorSchedulerWorkerCount,
65 > },
66 > logger,
67 > )
68 >
69 > return &memoryScheduledQueueFactory{
70 > scheduler: hostScheduler,
71 > priorityAssigner: queues.NewPriorityAssigner(
72 > params.NamespaceRegistry,
73 > params.ClusterMetadata.GetCurrentClusterName(),
74 > ),
75 > namespaceRegistry: params.NamespaceRegistry,
76 > clusterMetadata: params.ClusterMetadata,
77 > workflowCache: params.WorkflowCache,
78 > timeSource: params.TimeSource,
79 > chasmRegistry: params.ChasmRegistry,
80 > metricsHandler: metricsHandler,
81 > tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueMemory),
82 > logger: logger,
83 > executorWrapper: params.ExecutorWrapper,
84 > }
85 > }
86
87 > func (f *memoryScheduledQueueFactory) Start() { memory_scheduled_queue_factory.go
88 > f.scheduler.Start()
89 > }
90
91 > func (f *memoryScheduledQueueFactory) Stop() { memory_scheduled_queue_factory.go
92 > f.scheduler.Stop()
93 > }
94
95 func (f *memoryScheduledQueueFactory) CreateQueue(
96 shardCtx historyi.ShardContext,
97 > ) queues.Queue { memory_scheduled_queue_factory.go
98 >
99 > // Reuse TimerQueueActiveTaskExecutor only to executeWorkflowTaskTimeoutTask.
100 > // Unused dependencies are nil.
101 > speculativeWorkflowTaskTimeoutExecutor := newTimerQueueActiveTaskExecutor(
102 > shardCtx,
103 > f.workflowCache,
104 > nil,
105 > f.logger,
106 > f.metricsHandler,
107 > shardCtx.GetConfig(),
108 > nil,
109 > nil,
110 > )
111 > if f.executorWrapper != nil {
112 speculativeWorkflowTaskTimeoutExecutor = f.executorWrapper.Wrap(speculativeWorkflowTaskTimeoutExecutor)
113 }
114
115 > return queues.NewSpeculativeWorkflowTaskTimeoutQueue( memory_scheduled_queue_factory.go
116 > f.scheduler,
117 > f.priorityAssigner,
118 > speculativeWorkflowTaskTimeoutExecutor,
119 > f.namespaceRegistry,
120 > f.clusterMetadata,
121 > f.timeSource,
122 > f.chasmRegistry,
123 > f.metricsHandler,
124 > f.tracer,
125 > f.logger,
126 > )
127 }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/namespace.go 61 covered LOC · 16 ranges

Open complete file

45 ctx context.Context,
46 row *sqlplugin.NamespaceRow,
47 > ) (sql.Result, error) { namespace.go
48 > return mdb.conn.ExecContext(ctx,
49 > createNamespaceQuery,
50 > partitionID,
51 > row.ID,
52 > row.Name,
53 > row.IsGlobal,
54 > row.Data,
55 > row.DataEncoding,
56 > row.NotificationVersion,
57 > )
58 > }
59
60 // UpdateNamespace updates a single row in namespaces table
78 ctx context.Context,
79 filter sqlplugin.NamespaceFilter,
80 > ) ([]sqlplugin.NamespaceRow, error) { namespace.go
81 > switch {
82 > case filter.ID != nil || filter.Name != nil: namespace.go
83 > if filter.ID != nil && filter.Name != nil {
84 return nil, serviceerror.NewInternal("only ID or name filter can be specified for selection")
85 }
86 > return mdb.selectFromNamespace(ctx, filter) namespace.go
87 > case filter.PageSize != nil && *filter.PageSize > 0: namespace.go
88 > return mdb.selectAllFromNamespace(ctx, filter)
89 default:
90 return nil, errMissingArgs
95 ctx context.Context,
96 filter sqlplugin.NamespaceFilter,
97 > ) ([]sqlplugin.NamespaceRow, error) { namespace.go
98 > var err error
99 > var row sqlplugin.NamespaceRow
100 > switch {
101 case filter.ID != nil:
102 err = mdb.conn.GetContext(ctx,
106 *filter.ID,
107 )
108 > case filter.Name != nil: namespace.go
109 > err = mdb.conn.GetContext(ctx,
110 > &row,
111 > getNamespaceByNameQuery,
112 > partitionID,
113 > *filter.Name,
114 > )
115 }
116 > if err != nil { namespace.go
117 > return nil, err namespace.go
118 > }
119 > return []sqlplugin.NamespaceRow{row}, nil namespace.go
120 }
121
123 ctx context.Context,
124 filter sqlplugin.NamespaceFilter,
125 > ) ([]sqlplugin.NamespaceRow, error) { namespace.go
126 > var err error
127 > var rows []sqlplugin.NamespaceRow
128 > switch {
129 case filter.GreaterThanID != nil:
130 err = mdb.conn.SelectContext(ctx,
135 *filter.PageSize,
136 )
137 > default: namespace.go
138 > err = mdb.conn.SelectContext(ctx,
139 > &rows,
140 > listNamespacesQuery,
141 > partitionID,
142 > filter.PageSize,
143 > )
144 }
145 > return rows, err namespace.go
146 }
147
173 func (mdb *db) LockNamespaceMetadata(
174 ctx context.Context,
175 > ) (*sqlplugin.NamespaceMetadataRow, error) { namespace.go
176 > var row sqlplugin.NamespaceMetadataRow
177 > err := mdb.conn.GetContext(ctx,
178 > &row.NotificationVersion,
179 > lockNamespaceMetadataQuery,
180 > )
181 > if err != nil {
182 return nil, err
183 }
184 > return &row, nil namespace.go
185 }
186
201 ctx context.Context,
202 row *sqlplugin.NamespaceMetadataRow,
203 > ) (sql.Result, error) { namespace.go
204 > return mdb.conn.ExecContext(ctx,
205 > updateNamespaceMetadataQuery,
206 > row.NotificationVersion+1,
207 > row.NotificationVersion,
208 > )
209 > }
go.temporal.io/server/service/matching/service.go 61 covered LOC · 7 ranges

Open complete file

44 healthServer *health.Server,
45 visibilityManager manager.VisibilityManager,
46 > ) *Service { service.go
47 > return &Service{
48 > config: serviceConfig,
49 > server: server,
50 > handler: handler,
51 > logger: logger,
52 > membershipMonitor: membershipMonitor,
53 > grpcListener: grpcListener,
54 > runtimeMetricsReporter: runtimeMetricsReporter,
55 > metricsHandler: metricsHandler,
56 > healthServer: healthServer,
57 > visibilityManager: visibilityManager,
58 > }
59 > }
60
61 // Start starts the service
62 > func (s *Service) Start() { service.go
63 > s.logger.Info("matching starting")
64 >
65 > // must start base service first
66 > metrics.RestartCount.With(s.metricsHandler).Record(1)
67 >
68 > s.handler.Start()
69 >
70 > matchingservice.RegisterMatchingServiceServer(s.server, s.handler)
71 > healthpb.RegisterHealthServer(s.server, s.healthServer)
72 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_SERVING)
73 >
74 > reflection.Register(s.server)
75 >
76 > go func() {
77 > s.logger.Info("Starting to serve on matching listener")
78 > if err := s.server.Serve(s.grpcListener); err != nil {
79 s.logger.Fatal("Failed to serve on matching listener", tag.Error(err))
80 }
81 }()
82
83 > go s.membershipMonitor.Start() service.go
84 }
85
86 // Stop stops the service
87 > func (s *Service) Stop() { service.go
88 > // remove self from membership ring and wait for traffic to drain
89 > var err error
90 > var waitTime time.Duration
91 > if align := s.config.AlignMembershipChange(); align > 0 {
92 propagation := s.membershipMonitor.ApproximateMaxPropagationTime()
93 asOf := util.NextAlignedTime(time.Now().Add(propagation), align)
94 s.logger.Info("ShutdownHandler: Evicting self from membership ring as of", tag.Timestamp(asOf))
95 waitTime, err = s.membershipMonitor.EvictSelfAt(asOf)
96 > } else { service.go
97 > s.logger.Info("ShutdownHandler: Evicting self from membership ring immediately")
98 > err = s.membershipMonitor.EvictSelf()
99 > }
100 > if err != nil {
101 s.logger.Error("ShutdownHandler: Failed to evict self from membership ring", tag.Error(err))
102 }
103 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING) service.go
104 >
105 > s.logger.Info("ShutdownHandler: Waiting for others to discover I am unhealthy")
106 > time.Sleep(max(s.config.ShutdownDrainDuration(), waitTime))
107 >
108 > // At this point we should not get any new rpcs since we removed ourself from the ring.
109 > // Additionally, the engine will notice the membership change and stop all task queues
110 > // after a delay. However, we can do it immediately by stopping the handler (which stops
111 > // the engine which stops all task queues).
112 > s.handler.Stop()
113 >
114 > // All grpc handlers should be cancelled now. Give them a little time to return.
115 > t := time.AfterFunc(2*time.Second, func() {
116 s.logger.Info("ShutdownHandler: Drain time expired, stopping all traffic")
117 s.server.Stop()
118 })
119 > s.server.GracefulStop() service.go
120 > t.Stop()
121 >
122 > s.visibilityManager.Close()
123 >
124 > s.logger.Info("matching stopped")
125 }
go.temporal.io/server/service/worker/migration/fx.go 61 covered LOC · 7 ranges

Open complete file

57 )
58
59 > func NewResult(params initParams) fxResult { fx.go
60 > component := &replicationWorkerComponent{
61 > initParams: params,
62 > }
63 > return fxResult{
64 > Component: component,
65 > }
66 > }
67
68 > func (wc *replicationWorkerComponent) RegisterWorkflow(registry sdkworker.Registry) { fx.go
69 > registry.RegisterWorkflowWithOptions(CatchupWorkflow, workflow.RegisterOptions{Name: catchupWorkflowName})
70 > registry.RegisterWorkflowWithOptions(ForceReplicationWorkflow, workflow.RegisterOptions{Name: forceReplicationWorkflowName})
71 > registry.RegisterWorkflowWithOptions(ForceReplicationWorkflowV2, workflow.RegisterOptions{Name: forceReplicationWorkflowV2Name})
72 > registry.RegisterWorkflowWithOptions(NamespaceHandoverWorkflow, workflow.RegisterOptions{Name: namespaceHandoverWorkflowName})
73 > registry.RegisterWorkflowWithOptions(NamespaceHandoverWorkflowV2, workflow.RegisterOptions{Name: namespaceHandoverWorkflowV2Name})
74 > registry.RegisterWorkflowWithOptions(ForceTaskQueueUserDataReplicationWorkflow, workflow.RegisterOptions{Name: forceTaskQueueUserDataReplicationWorkflow})
75 > }
76
77 > func (wc *replicationWorkerComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
78 > // Use default worker
79 > return nil
80 > }
81
82 > func (wc *replicationWorkerComponent) RegisterActivities(registry sdkworker.Registry) { fx.go
83 > registry.RegisterActivity(wc.activities())
84 > }
85
86 > func (wc *replicationWorkerComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
87 > return &workercommon.DedicatedWorkerOptions{
88 > TaskQueue: primitives.MigrationActivityTQ,
89 > Options: sdkworker.Options{
90 > BackgroundActivityContext: headers.SetCallerType(context.Background(), headers.CallerTypePreemptable),
91 > },
92 > }
93 > }
94
95 > func workflowVerifierProvider() WorkflowVerifier { fx.go
96 > return func(
97 > _ context.Context,
98 > _ *verifyReplicationTasksRequest,
99 > _ adminservice.AdminServiceClient,
100 > _ adminservice.AdminServiceClient,
101 > _ *namespace.Namespace,
102 > _ *ExecutionInfo,
103 > _ *adminservice.DescribeMutableStateResponse,
104 > ) (verifyResult, error) {
105 return verifyResult{
106 status: verified,
109 }
110
111 > func (wc *replicationWorkerComponent) activities() *activities { fx.go
112 > return &activities{
113 > HistoryShardCount: wc.PersistenceConfig.NumHistoryShards,
114 > executionManager: wc.ExecutionManager,
115 > NamespaceRegistry: wc.NamespaceRegistry,
116 > HistoryClient: wc.HistoryClient,
117 > frontendClient: wc.FrontendClient,
118 > clientFactory: wc.ClientFactory,
119 > clientBean: wc.ClientBean,
120 > namespaceReplicationQueue: wc.NamespaceReplicationQueue,
121 > taskManager: wc.TaskManager,
122 > Logger: wc.Logger,
123 > MetricsHandler: wc.MetricsHandler,
124 > forceReplicationMetricsHandler: wc.MetricsHandler.WithTags(metrics.WorkflowTypeTag(forceReplicationWorkflowName)),
125 > generateMigrationTaskViaFrontend: dynamicconfig.WorkerGenerateMigrationTaskViaFrontend.Get(wc.DynamicCollection),
126 > enableHistoryRateLimiter: dynamicconfig.WorkerEnableHistoryRateLimiter.Get(wc.DynamicCollection),
127 > workflowVerifier: wc.WorkflowVerifier,
128 > chasmRegistry: wc.ChasmRegistry,
129 > }
130 > }
go.temporal.io/server/common/goro/adaptive_pool.go 60 covered LOC · 21 ranges

Open complete file

32 targetDelay time.Duration,
33 shrinkFactor float64,
34 > ) *AdaptivePool { adaptive_pool.go
35 > p := &AdaptivePool{
36 > ts: ts,
37 > minWorkers: minWorkers,
38 > maxWorkers: maxWorkers,
39 > targetDelay: targetDelay,
40 > shrinkFactor: shrinkFactor,
41 > ch: make(chan func()),
42 > stopCh: make(chan struct{}),
43 > }
44 > for range minWorkers {
45 go p.work()
46 }
47 > p.workers.Store(int64(minWorkers)) adaptive_pool.go
48 > return p
49 }
50
52 // When Stop is called, concurrent calls to Do may or may not call their function, and future
53 // calls definitely won't.
54 > func (p *AdaptivePool) Stop() { adaptive_pool.go
55 > close(p.stopCh)
56 > }
57
58 // Do calls f() on a worker goroutine. If the call can't be started within targetDelay, it adds
59 // another worker. If Stop is called concurrently, Do may or may not call f. If Stop has been
60 // called already, Do does nothing.
61 > func (p *AdaptivePool) Do(f func()) { adaptive_pool.go
62 > // try send first
63 > select {
64 > case p.ch <- f: adaptive_pool.go
65 > return
66 > default: adaptive_pool.go
67 }
68
69 // we might want to add a worker, send with timeout
70 > have := p.workers.Load() adaptive_pool.go
71 > if have < int64(p.maxWorkers) {
72 > timech, timer := p.ts.NewTimer(p.targetDelay) adaptive_pool.go
73 > select {
74 case <-p.stopCh:
75 timer.Stop()
76 return
77 > case p.ch <- f: adaptive_pool.go
78 > timer.Stop()
79 > return
80 > case <-timech: adaptive_pool.go
81 }
82
83 > if p.workers.CompareAndSwap(have, have+1) { adaptive_pool.go
84 > go p.work()
85 > }
86 }
87
88 // blocking send
89 > select { adaptive_pool.go
90 > case p.ch <- f:
91 case <-p.stopCh:
92 }
93 }
94
95 > func (p *AdaptivePool) work() { adaptive_pool.go
96 > for {
97 > // try receive first
98 > select {
99 > case f := <-p.ch: adaptive_pool.go
100 > f()
101 > continue
102 > default: adaptive_pool.go
103 }
104
105 > have := p.workers.Load() adaptive_pool.go
106 > if have > int64(p.minWorkers) {
107 > // we might want to exit, receive with timeout adaptive_pool.go
108 > // jitter this so we shrink slower than we grow
109 > timech, timer := p.ts.NewTimer(time.Duration(float64(p.targetDelay) * p.shrinkFactor * rand.Float64()))
110 > select {
111 > case <-p.stopCh: adaptive_pool.go
112 > timer.Stop()
113 > return
114 > case f := <-p.ch: adaptive_pool.go
115 > timer.Stop()
116 > f()
117 > continue
118 > case <-timech: adaptive_pool.go
119 }
120 > if p.workers.CompareAndSwap(have, have-1) { adaptive_pool.go
121 > return
122 > }
123 }
124
go.temporal.io/server/common/log/tag/zap_tag.go 60 covered LOC · 14 ranges

Open complete file

44 }
45
46 > func NewStringTag(key string, value string) ZapTag { zap_tag.go
47 > return ZapTag{
48 > field: zap.String(key, value),
49 > }
50 > }
51
52 > func NewStringsTag(key string, value []string) ZapTag { zap_tag.go
53 > return ZapTag{
54 > field: zap.Strings(key, value),
55 > }
56 > }
57
58 // NewStringerTag returns a tag that will lazily generate the string representation
63 // These are still useful if the String() implementation is complicated, especially if
64 // you have lots of Debug-level logs that are ignored in production.
65 > func NewStringerTag(key string, value fmt.Stringer) ZapTag { zap_tag.go
66 > return ZapTag{
67 > field: zap.Stringer(key, value),
68 > }
69 > }
70
71 // NewStringersTag returns a tag that will lazily generate the string representation
82 }
83
84 > func NewInt64(key string, value int64) ZapTag { zap_tag.go
85 > return ZapTag{
86 > field: zap.Int64(key, value),
87 > }
88 > }
89
90 > func NewInt(key string, value int) ZapTag { zap_tag.go
91 > return ZapTag{
92 > field: zap.Int(key, value),
93 > }
94 > }
95
96 > func NewInt32(key string, value int32) ZapTag { zap_tag.go
97 > return ZapTag{
98 > field: zap.Int32(key, value),
99 > }
100 > }
101
102 func NewUInt32(key string, value uint32) ZapTag {
118 }
119
120 > func NewBoolTag(key string, value bool) ZapTag { zap_tag.go
121 > return ZapTag{
122 > field: zap.Bool(key, value),
123 > }
124 > }
125
126 func NewErrorTag(key string, value error) ZapTag {
130 }
131
132 > func NewDurationTag(key string, value time.Duration) ZapTag { zap_tag.go
133 > return ZapTag{
134 > field: zap.Duration(key, value),
135 > }
136 > }
137
138 func NewDurationPtrTag(key string, value *durationpb.Duration) ZapTag {
154 }
155
156 > func NewAnyTag(key string, value any) ZapTag { zap_tag.go
157 > return ZapTag{
158 > field: zap.Any(key, value),
159 > }
160 > }
161
162 func NewBinaryTag(key string, value []byte) ZapTag {
168 // Shorter helpers (aliases for the New* functions above)
169
170 > func String(key string, value string) ZapTag { zap_tag.go
171 > return NewStringTag(key, value)
172 > }
173
174 func Strings(key string, value []string) ZapTag {
176 }
177
178 > func Stringer(key string, value fmt.Stringer) ZapTag { zap_tag.go
179 > return NewStringerTag(key, value)
180 > }
181
182 func Stringers(key string, value []fmt.Stringer) ZapTag {
188 }
189
190 > func Int(key string, value int) ZapTag { zap_tag.go
191 > return NewInt(key, value)
192 > }
193
194 func Int32(key string, value int32) ZapTag {
208 }
209
210 > func Duration(key string, value time.Duration) ZapTag { zap_tag.go
211 > return NewDurationTag(key, value)
212 > }
213
214 func DurationPtr(key string, value *durationpb.Duration) ZapTag {
224 }
225
226 > func Any(key string, value any) ZapTag { zap_tag.go
227 > return NewAnyTag(key, value)
228 > }
229
230 func Binary(key string, value []byte) ZapTag {
go.temporal.io/server/chasm/registrable_task.go 59 covered LOC · 12 ranges

Open complete file

50 handler SideEffectTaskHandler[C, T],
51 opts ...RegistrableTaskOption,
52 > ) *RegistrableTask { registrable_task.go
53 > return newRegistrableTask(
54 > taskType,
55 > reflect.TypeFor[T](),
56 > reflect.TypeFor[C](),
57 > func(
58 > ctx Context,
59 > component any,
60 > taskInvocation TaskInvocation,
61 > taskData any,
62 > registry *Registry,
63 > ) (bool, error) {
64 return handler.Validate(
65 ctx,
90 handler PureTaskHandler[C, T],
91 opts ...RegistrableTaskOption,
92 > ) *RegistrableTask { registrable_task.go
93 > return newRegistrableTask(
94 > taskType,
95 > reflect.TypeFor[T](),
96 > reflect.TypeFor[C](),
97 > func(
98 > ctx Context,
99 > component any,
100 > taskInvocation TaskInvocation,
101 > taskData any,
102 > registry *Registry,
103 > ) (bool, error) {
104 return handler.Validate(
105 ctx,
139 sideEffectTaskDiscardFn sideEffectTaskDiscardFn,
140 opts ...RegistrableTaskOption,
141 > ) *RegistrableTask { registrable_task.go
142 > rt := &RegistrableTask{
143 > taskType: taskType,
144 > goType: goType,
145 > componentGoType: componentGoType,
146 > validateFn: validateFn,
147 > pureTaskExecuteFn: pureTaskExecuteFn,
148 > sideEffectTaskExecuteFn: sideEffectTaskExecuteFn,
149 > sideEffectTaskDiscardFn: sideEffectTaskDiscardFn,
150 > isPureTask: isPureTask,
151 > }
152 >
153 > for _, opt := range opts {
154 > opt(rt) registrable_task.go
155 > }
156
157 > return rt registrable_task.go
158 }
159
160 func (rt *RegistrableTask) registerToLibrary(
161 library namer,
162 > ) (string, uint32, error) { registrable_task.go
163 > if rt.library != nil {
164 return "", 0, fmt.Errorf("task %s is already registered in library %s", rt.taskType, rt.library.Name())
165 }
166
167 > rt.library = library registrable_task.go
168 >
169 > fqn := rt.fqType()
170 > rt.taskTypeID = GenerateTypeID(fqn)
171 > // If outboundTaskGroup wasn't set on creation default it here,
172 > // since this is the first place we will have the fqn.
173 > if rt.outboundTaskGroup == "" {
174 > rt.outboundTaskGroup = fqn registrable_task.go
175 > }
176 > return fqn, rt.taskTypeID, nil registrable_task.go
177 }
178
190 // the library name and the task type. This is used to uniquely identify
191 // the task in the registry.
192 > func (rt *RegistrableTask) fqType() string { registrable_task.go
193 > if rt.library == nil {
194 // this should never happen because the task is only accessible from the library.
195 panic("task is not registered to a library")
196 }
197 > return FullyQualifiedName(rt.library.Name(), rt.taskType) registrable_task.go
198 }
199
202 // affects multi-cursor and the circuit breaker.
203 // If task group isn't provided, the task group will default to the fully qualified name at library registration.
204 > func WithTaskGroup(taskgroup string) RegistrableTaskOption { registrable_task.go
205 > return func(rt *RegistrableTask) {
206 > rt.outboundTaskGroup = taskgroup
207 > }
208 }
209
go.temporal.io/server/common/config/persistence.go 59 covered LOC · 27 ranges

Open complete file

25
26 // DefaultStoreType returns the storeType for the default persistence store
27 > func (c *Persistence) DefaultStoreType() string { persistence.go
28 > if c.DataStores[c.DefaultStore].SQL != nil {
29 > return StoreTypeSQL persistence.go
30 > }
31 return StoreTypeNoSQL
32 }
33
34 // Validate validates the persistence config
35 > func (c *Persistence) Validate() error { persistence.go
36 > stores := []string{c.DefaultStore}
37 > if c.VisibilityStore != "" {
38 > stores = append(stores, c.VisibilityStore)
39 > }
40 > if c.SecondaryVisibilityStore != "" {
41 stores = append(stores, c.SecondaryVisibilityStore)
42 }
57 // - visibilityStore (es), secondaryVisibilityStore (advanced sql)
58
59 > if c.VisibilityStore == "" { persistence.go
60 return fmt.Errorf("%w: visibilityStore must be specified", ErrPersistenceConfig)
61 }
62 > if c.SecondaryVisibilityStore != "" { persistence.go
63 isAnyCustom := c.DataStores[c.VisibilityStore].CustomDataStoreConfig != nil ||
64 c.DataStores[c.SecondaryVisibilityStore].CustomDataStoreConfig != nil
84 }
85
86 > for _, st := range stores { persistence.go
87 > ds, ok := c.DataStores[st]
88 > if !ok {
89 return fmt.Errorf("%w: missing config for datastore %q", ErrPersistenceConfig, st)
90 }
91 > if err := ds.Validate(); err != nil { persistence.go
92 return fmt.Errorf("%w: datastore %q: %s", ErrPersistenceConfig, st, err.Error())
93 }
94 }
95 > return nil persistence.go
96 }
97
98 // VisibilityConfigExist returns whether user specified visibilityStore in config
99 > func (c *Persistence) VisibilityConfigExist() bool { persistence.go
100 > return c.VisibilityStore != ""
101 > }
102
103 // SecondaryVisibilityConfigExist returns whether user specified secondaryVisibilityStore in config
104 > func (c *Persistence) SecondaryVisibilityConfigExist() bool { persistence.go
105 > return c.SecondaryVisibilityStore != ""
106 > }
107
108 func (c *Persistence) IsSQLVisibilityStore() bool {
116 }
117
118 > func (c *Persistence) GetVisibilityStoreConfig() DataStore { persistence.go
119 > return c.DataStores[c.VisibilityStore]
120 > }
121
122 > func (c *Persistence) GetSecondaryVisibilityStoreConfig() DataStore { persistence.go
123 > if c.SecondaryVisibilityStore != "" {
124 return c.DataStores[c.SecondaryVisibilityStore]
125 }
126 > if c.VisibilityStore != "" { persistence.go
127 > ds := c.DataStores[c.VisibilityStore]
128 > if ds.Elasticsearch != nil && ds.Elasticsearch.GetSecondaryVisibilityIndex() != "" {
129 esConfig := *ds.Elasticsearch
130 esConfig.Indices = map[string]string{
135 }
136 }
137 > return DataStore{} persistence.go
138 }
139
140 > func (ds *DataStore) GetIndexName() string { persistence.go
141 > switch {
142 > case ds.SQL != nil:
143 > return ds.SQL.DatabaseName
144 case ds.Cassandra != nil:
145 return ds.Cassandra.Keyspace
148 case ds.CustomDataStoreConfig != nil:
149 return ds.CustomDataStoreConfig.IndexName
150 > default: persistence.go
151 > return ""
152 }
153 }
154
155 // Validate validates the data store config
156 > func (ds *DataStore) Validate() error { persistence.go
157 > storeConfigCount := 0
158 > if ds.SQL != nil {
159 > storeConfigCount++
160 > }
161 > if ds.Cassandra != nil {
162 storeConfigCount++
163 }
164 > if ds.CustomDataStoreConfig != nil { persistence.go
165 storeConfigCount++
166 }
167 > if ds.Elasticsearch != nil { persistence.go
168 storeConfigCount++
169 }
170 > if storeConfigCount != 1 { persistence.go
171 return errors.New(
172 "must provide config for one and only one datastore: " +
175 }
176
177 > if ds.SQL != nil { persistence.go
178 > if ds.SQL.TaskScanPartitions == 0 {
179 > ds.SQL.TaskScanPartitions = 1
180 > }
181 > if err := ds.SQL.validate(); err != nil {
182 return err
183 }
184 }
185 > if ds.Cassandra != nil { persistence.go
186 if err := ds.Cassandra.validate(); err != nil {
187 return err
188 }
189 }
190 > if ds.Elasticsearch != nil { persistence.go
191 if err := ds.Elasticsearch.Validate(); err != nil {
192 return err
193 }
194 }
195 > return nil persistence.go
196 }
197
282 }
283
284 > func (c *SQL) validate() error { persistence.go
285 > if c.PasswordCommand != nil && c.Password != "" {
286 return errors.New("passwordCommand and password are mutually exclusive")
287 }
288 > if c.PasswordCommand != nil && c.PasswordCommand.Command == "" { persistence.go
289 return errors.New("passwordCommand.command must not be empty")
290 }
291 > return nil persistence.go
292 }
293
go.temporal.io/server/common/persistence/sql/shard.go 59 covered LOC · 14 ranges

Open complete file

24 logger log.Logger,
25 serializer serialization.Serializer,
26 > ) (persistence.ShardStore, error) { shard.go
27 > return &sqlShardStore{
28 > SqlStore: NewSQLStore(db, logger, serializer),
29 > currentClusterName: currentClusterName,
30 > }, nil
31 > }
32
33 func (m *sqlShardStore) GetClusterName() string {
38 ctx context.Context,
39 request *persistence.InternalGetOrCreateShardRequest,
40 > ) (*persistence.InternalGetOrCreateShardResponse, error) { shard.go
41 > row, err := m.DB.SelectFromShards(ctx, sqlplugin.ShardsFilter{
42 > ShardID: request.ShardID,
43 > })
44 > switch err {
45 case nil:
46 return &persistence.InternalGetOrCreateShardResponse{
47 ShardInfo: persistence.NewDataBlob(row.Data, row.DataEncoding),
48 }, nil
49 > case sql.ErrNoRows: shard.go
50 default:
51 return nil, serviceerror.NewUnavailablef("GetOrCreateShard: failed to get ShardID %v. Error: %v", request.ShardID, err)
52 }
53
54 > if request.CreateShardInfo == nil { shard.go
55 return nil, serviceerror.NewNotFoundf("GetOrCreateShard: ShardID %v not found. Error: %v", request.ShardID, err)
56 }
57
58 > rangeID, shardInfo, err := request.CreateShardInfo() shard.go
59 > if err != nil {
60 return nil, serviceerror.NewUnavailablef("GetOrCreateShard: failed to encode shard info for ShardID %v. Error: %v", request.ShardID, err)
61 }
62 > row = &sqlplugin.ShardsRow{ shard.go
63 > ShardID: request.ShardID,
64 > RangeID: rangeID,
65 > Data: shardInfo.Data,
66 > DataEncoding: shardInfo.EncodingType.String(),
67 > }
68 > _, err = m.DB.InsertIntoShards(ctx, row)
69 > if err == nil {
70 > return &persistence.InternalGetOrCreateShardResponse{
71 > ShardInfo: shardInfo,
72 > }, nil
73 > } else if m.DB.IsDupEntryError(err) {
74 // conflict, try again
75 request.CreateShardInfo = nil // prevent loop
83 ctx context.Context,
84 request *persistence.InternalUpdateShardRequest,
85 > ) error { shard.go
86 > return m.txExecute(ctx, "UpdateShard", func(tx sqlplugin.Tx) error {
87 > if err := lockShard(ctx,
88 > tx,
89 > request.ShardID,
90 > request.PreviousRangeID,
91 > m.logger,
92 > ); err != nil {
93 return err
94 }
95 > result, err := tx.UpdateShards(ctx, &sqlplugin.ShardsRow{ shard.go
96 > ShardID: request.ShardID,
97 > RangeID: request.RangeID,
98 > Data: request.ShardInfo.Data,
99 > DataEncoding: request.ShardInfo.EncodingType.String(),
100 > })
101 > if err != nil {
102 return err
103 }
104 > rowsAffected, err := result.RowsAffected() shard.go
105 > if err != nil {
106 return fmt.Errorf("rowsAffected returned error for shardID %v: %v", request.ShardID, err)
107 }
108 > if rowsAffected != 1 { shard.go
109 return fmt.Errorf("rowsAffected returned %v shards instead of one", rowsAffected)
110 }
111 > return nil shard.go
112 })
113 }
116 ctx context.Context,
117 request *persistence.AssertShardOwnershipRequest,
118 > ) error { shard.go
119 > // AssertShardOwnership is not implemented for sql shard store
120 > return nil
121 > }
122
123 // initiated by the owning shard
128 oldRangeID int64,
129 logger log.Logger,
130 > ) error { shard.go
131 >
132 > rangeID, err := tx.WriteLockShards(ctx, sqlplugin.ShardsFilter{
133 > ShardID: shardID,
134 > })
135 > switch err {
136 > case nil:
137 > if rangeID != oldRangeID {
138 return &persistence.ShardOwnershipLostError{
139 ShardID: shardID,
141 }
142 }
143 > return nil shard.go
144 case sql.ErrNoRows:
145 return serviceerror.NewUnavailablef("Failed to lock shard with ID %v that does not exist.", shardID)
go.temporal.io/server/common/rpc/encryption/local_store_tls_provider.go 59 covered LOC · 12 ranges

Open complete file

54
55 func NewLocalStoreTlsProvider(tlsConfig *config.RootTLS, metricsHandler metrics.Handler, logger log.Logger, certProviderFactory CertProviderFactory,
56 > ) (TLSConfigProvider, error) { local_store_tls_provider.go
57 >
58 > internodeProvider := certProviderFactory(&tlsConfig.Internode, nil, nil, tlsConfig.RefreshInterval, logger)
59 > var workerProvider CertProvider
60 > if isSystemWorker(tlsConfig) { // explicit system worker config
61 workerProvider = certProviderFactory(nil, &tlsConfig.SystemWorker, nil, tlsConfig.RefreshInterval, logger)
62 > } else { // legacy implicit system worker config case local_store_tls_provider.go
63 > internodeWorkerProvider := certProviderFactory(&tlsConfig.Internode, nil, &tlsConfig.Frontend.Client, tlsConfig.RefreshInterval, logger)
64 > workerProvider = internodeWorkerProvider
65 > }
66
67 > remoteClusterClientCertProvider := make(map[string]CertProvider) local_store_tls_provider.go
68 > for key, groupTLS := range tlsConfig.RemoteClusters {
69 remoteClusterClientCertProvider[key] = certProviderFactory(&groupTLS, nil, nil, tlsConfig.RefreshInterval, logger)
70 }
71
72 > provider := &localStoreTlsProvider{ local_store_tls_provider.go
73 > internodeCertProvider: internodeProvider,
74 > internodeClientCertProvider: internodeProvider,
75 > frontendCertProvider: certProviderFactory(&tlsConfig.Frontend, nil, nil, tlsConfig.RefreshInterval, logger),
76 > workerCertProvider: workerProvider,
77 > frontendPerHostCertProviderMap: newLocalStorePerHostCertProviderMap(
78 > tlsConfig.Frontend.PerHostOverrides, certProviderFactory, tlsConfig.RefreshInterval, logger),
79 > remoteClusterClientCertProvider: remoteClusterClientCertProvider,
80 > RWMutex: sync.RWMutex{},
81 > settings: tlsConfig,
82 > metricsHandler: metricsHandler,
83 > logger: logger,
84 > cachedRemoteClusterClientConfig: make(map[string]*tls.Config),
85 > }
86 > provider.initialize()
87 > return provider, nil
88 }
89
90 > func (s *localStoreTlsProvider) initialize() { local_store_tls_provider.go
91 > period := s.settings.ExpirationChecks.CheckInterval
92 > if period != 0 {
93 s.stop = make(chan bool)
94 s.ticker = time.NewTicker(period)
122 }
123
124 > func (s *localStoreTlsProvider) GetFrontendClientConfig() (*tls.Config, error) { local_store_tls_provider.go
125 >
126 > var client *config.ClientTLS
127 > var useTLS bool
128 > if isSystemWorker(s.settings) {
129 client = &s.settings.SystemWorker.Client
130 useTLS = true
132 > client = &s.settings.Frontend.Client
133 > useTLS = s.settings.Frontend.IsClientEnabled()
134 > }
135 > return s.getOrCreateConfig(
136 > &s.cachedFrontendClientConfig,
137 > func() (*tls.Config, error) {
138 return newClientTLSConfig(s.workerCertProvider, client.ServerName,
139 useTLS, true, !client.DisableHostVerification)
163 }
164
165 > func (s *localStoreTlsProvider) GetFrontendServerConfig() (*tls.Config, error) { local_store_tls_provider.go
166 > return s.getOrCreateConfig(
167 > &s.cachedFrontendServerConfig,
168 > func() (*tls.Config, error) {
169 return newServerTLSConfig(s.frontendCertProvider, s.frontendPerHostCertProviderMap, &s.settings.Frontend, s.logger)
170 },
172 }
173
174 > func (s *localStoreTlsProvider) GetInternodeServerConfig() (*tls.Config, error) { local_store_tls_provider.go
175 > return s.getOrCreateConfig(
176 > &s.cachedInternodeServerConfig,
177 > func() (*tls.Config, error) {
178 return newServerTLSConfig(s.internodeCertProvider, nil, &s.settings.Internode, s.logger)
179 },
473 }
474
475 > func isSystemWorker(tls *config.RootTLS) bool { local_store_tls_provider.go
476 > return tls.SystemWorker.CertData != "" || tls.SystemWorker.CertFile != "" ||
477 > len(tls.SystemWorker.Client.RootCAData) > 0 || len(tls.SystemWorker.Client.RootCAFiles) > 0 ||
478 > tls.SystemWorker.Client.ForceTLS
479 > }
480
481 // matchRemoteClusterKey checks exact matches, then finds the match with the most non-wildcard characters
go.temporal.io/server/common/sdk/factory.go 59 covered LOC · 12 ranges

Open complete file

56 logger log.Logger,
57 stickyCacheSize dynamicconfig.IntPropertyFn,
58 > ) *clientFactory { factory.go
59 > return &clientFactory{
60 > hostPort: hostPort,
61 > tlsConfig: tlsConfig,
62 > metricsHandler: NewMetricsHandler(metricsHandler),
63 > logger: logger,
64 > sdklogger: log.NewSdkLogger(logger),
65 > stickyCacheSize: stickyCacheSize,
66 > }
67 > }
68
69 > func (f *clientFactory) options(options sdkclient.Options) sdkclient.Options { factory.go
70 > options.HostPort = f.hostPort
71 > options.MetricsHandler = f.metricsHandler
72 > options.Logger = f.sdklogger
73 > options.ConnectionOptions = sdkclient.ConnectionOptions{
74 > TLS: f.tlsConfig,
75 > DialOptions: []grpc.DialOption{
76 > grpc.WithUnaryInterceptor(sdkClientNameHeadersInjectorInterceptor()),
77 > },
78 > }
79 > return options
80 > }
81
82 > func (f *clientFactory) NewClient(options sdkclient.Options) sdkclient.Client { factory.go
83 > // this shouldn't fail if the first client was created successfully
84 > client, err := sdkclient.NewClientFromExisting(f.GetSystemClient(), f.options(options))
85 > if err != nil {
86 f.logger.Fatal("error creating sdk client", tag.Error(err))
87 }
88 > return client factory.go
89 }
90
91 > func (f *clientFactory) GetSystemClient() sdkclient.Client { factory.go
92 > f.once.Do(func() {
93 > err := backoff.ThrottleRetry(func() error {
94 > sdkClient, err := sdkclient.Dial(f.options(sdkclient.Options{
95 > Namespace: primitives.SystemLocalNamespace,
96 > }))
97 > if err != nil {
98 f.logger.Warn("error creating sdk client", tag.Error(err))
99 return err
100 }
101 > f.systemSdkClient = sdkClient factory.go
102 > return nil
103 }, common.CreateSdkClientFactoryRetryPolicy(), func(err error) bool {
104 // note err is wrapped by sdk
106 return common.IsContextDeadlineExceededErr(err) || errors.As(err, &unavail)
107 })
108 > if err != nil { factory.go
109 f.logger.Fatal("error creating sdk client", tag.Error(err))
110 }
111
112 > if size := f.stickyCacheSize(); size > 0 { factory.go
113 f.logger.Info("setting sticky workflow cache size", tag.Int("size", size))
114 sdkworker.SetStickyWorkflowCacheSize(size)
115 }
116 })
117 > return f.systemSdkClient factory.go
118 }
119
122 taskQueue string,
123 options sdkworker.Options,
124 > ) sdkworker.Worker { factory.go
125 > return sdkworker.New(client, taskQueue, options)
126 > }
127
128 // Overwrite the 'client-name' and 'client-version' headers on gRPC requests sent using the Go SDK
129 // so they clearly indicate that the request is coming from the Temporal server.
130 > func sdkClientNameHeadersInjectorInterceptor() grpc.UnaryClientInterceptor { factory.go
131 > return func(
132 > ctx context.Context,
133 > method string,
134 > req, reply any,
135 > cc *grpc.ClientConn,
136 > invoker grpc.UnaryInvoker,
137 > opts ...grpc.CallOption,
138 > ) error {
139 > // Can't use headers.SetVersions() here because it is _appending_ headers to the context
140 > // rather than _replacing_ them, which means Go SDK's default headers would still be present.
141 > md, mdExist := metadata.FromOutgoingContext(ctx)
142 > if !mdExist {
143 md = metadata.New(nil)
144 }
145 > md.Set(headers.ClientNameHeaderName, headers.ClientNameServer) factory.go
146 > md.Set(headers.ClientVersionHeaderName, headers.ServerVersion)
147 > ctx = metadata.NewOutgoingContext(ctx, md)
148 > return invoker(ctx, method, req, reply, cc, opts...)
149 }
150 }
go.temporal.io/server/temporaltest/server.go 58 covered LOC · 12 ranges

Open complete file

66 //
67 // It is configured to use a pre-registered test namespace and will be closed on TestServer.Stop.
68 > func (ts *TestServer) GetDefaultClient() client.Client { server.go
69 > if ts.defaultClient == nil {
70 > ts.defaultClient = ts.NewClientWithOptions(ts.defaultClientOptions)
71 > }
72 > return ts.defaultClient
73 }
74
90 // If no namespace option is set it will use a pre-registered test namespace.
91 // The returned client will be closed on TestServer.Stop.
92 > func (ts *TestServer) NewClientWithOptions(opts client.Options) client.Client { server.go
93 > if opts.Namespace == "" {
94 > opts.Namespace = ts.defaultTestNamespace
95 > }
96 > if opts.Logger == nil {
97 > opts.Logger = &testLogger{ts.t}
98 > }
99
100 > ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) server.go
101 > defer cancel()
102 >
103 > c, err := ts.server.NewClientWithOptions(ctx, opts)
104 > if err != nil {
105 ts.fatal(fmt.Errorf("error creating client: %w", err))
106 }
107
108 > ts.clients = append(ts.clients, c) server.go
109 >
110 > return c
111 }
112
113 // Stop closes test clients and shuts down the server.
114 > func (ts *TestServer) Stop() { server.go
115 > for _, w := range ts.workers {
116 w.Stop()
117 }
118 > for _, c := range ts.clients { server.go
119 > c.Close()
120 > }
121 > if err := ts.server.Stop(); err != nil {
122 // Log instead of throwing error because there's no need to fail the test
123 // if it already succeeded.
130 // If not specifying the WithT option, the caller should execute Stop when finished to close
131 // the server and release resources.
132 > func NewServer(opts ...TestServerOption) *TestServer { server.go
133 > testNamespace := fmt.Sprintf("temporaltest-%d", rand.Intn(1e6))
134 >
135 > ts := TestServer{
136 > defaultTestNamespace: testNamespace,
137 > }
138 >
139 > // Apply options
140 > for _, opt := range opts {
141 > opt.apply(&ts)
142 > }
143
144 > if ts.t != nil { server.go
145 > ts.t.Cleanup(ts.Stop) server.go
146 > }
147
148 > s, err := temporalite.NewLiteServer(&temporalite.LiteServerConfig{ server.go
149 > Namespaces: []string{ts.defaultTestNamespace},
150 > Ephemeral: true,
151 > Logger: log.NewNoopLogger(),
152 > DynamicConfig: dynamicconfig.StaticClient{
153 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Key(): []dynamicconfig.ConstrainedValue{{Value: true}},
154 > },
155 > // Disable "accept incoming network connections?" prompt on macOS
156 > FrontendIP: "127.0.0.1",
157 > }, ts.serverOptions...)
158 > if err != nil {
159 ts.fatal(fmt.Errorf("error creating server: %w", err))
160 }
161 > ts.server = s server.go
162 >
163 > // Start does not block as long as InterruptOn is unset.
164 > if err := s.Start(); err != nil {
165 ts.fatal(err)
166 }
167
168 // This sleep helps avoid a panic in github.com/temporalio/[email protected]/swim/labels.go:175
169 > time.Sleep(100 * time.Millisecond) server.go
170 >
171 > return &ts
172 }
go.temporal.io/server/client/matching/client.go 57 covered LOC · 12 ranges

Open complete file

61 resolver membership.ServiceResolver,
62 connectionCloseDelay dynamicconfig.DurationPropertyFn,
63 > ) matchingservice.MatchingServiceClient { client.go
64 > c := &clientImpl{
65 > timeout: timeout,
66 > longPollTimeout: longPollTimeout,
67 > clients: clients,
68 > resolver: resolver,
69 > connectionCloseDelay: connectionCloseDelay,
70 > metricsHandler: metricsHandler,
71 > logger: logger,
72 > loadBalancer: lb,
73 > spreadRouting: spreadRouting,
74 > partitionCache: newPartitionCache(metricsHandler),
75 > }
76 >
77 > // Start goroutine to prune partition count cache. Stopped by Stop().
78 > c.partitionCache.Start()
79 >
80 > // Evict cached clients whose host leaves the membership ring. Stopped by Stop().
81 > c.evictionWatcher = goro.NewHandle(context.Background()).Go(c.watchMembership)
82 >
83 > return c
84 > }
85
86 // Stop deterministically releases the resources started by NewClient: it stops
87 // the eviction watcher and partition-cache rotation goroutines and closes every
88 // cached gRPC connection. It is safe to call more than once.
89 > func (c *clientImpl) Stop() { client.go
90 > c.evictionWatcher.Cancel()
91 > <-c.evictionWatcher.Done()
92 > c.partitionCache.Stop()
93 > c.clients.EvictAll()
94 > }
95
96 // watchMembership evicts cached clients whose host leaves the membership ring.
97 // It runs until ctx is cancelled (by Stop).
98 > func (c *clientImpl) watchMembership(ctx context.Context) error { client.go
99 > listenerName := fmt.Sprintf("matchingClientCache-%s", uuid.New().String())
100 > ch := make(chan *membership.ChangedEvent, 1)
101 > if err := c.resolver.AddListener(listenerName, ch); err != nil {
102 c.logger.Error("Failed to subscribe matching cache to membership", tag.Error(err))
103 return err
104 }
105 > defer func() { _ = c.resolver.RemoveListener(listenerName) }() client.go
106
107 // Reap departed hosts via a per-address deadline checked by a single ticker;
108 // a re-add resets it to the latest removal.
109 > evictAt := make(map[string]time.Time) client.go
110 > ticker := time.NewTicker(evictionCheckInterval)
111 > defer ticker.Stop()
112 > for {
113 > select {
114 > case <-ctx.Done(): client.go
115 > return nil
116 > case event := <-ch: client.go
117 > for _, h := range event.HostsRemoved {
118 > evictAt[h.GetAddress()] = time.Now().Add(c.connectionCloseDelay()) client.go
119 > }
120 > for _, h := range event.HostsAdded { client.go
121 > delete(evictAt, h.GetAddress())
122 > }
123 case <-ticker.C:
124 reapEvictableClients(c.resolver, c.clients, evictAt)
510 }
511
512 > func (c *clientImpl) Route(p tqid.Partition) (string, error) { client.go
513 > spreadChange := c.spreadRouting()
514 > spread := spreadChange.Value(p.GradualChangeKey(), time.Now())
515 > return c.clients.Lookup(p.RoutingKey(spread))
516 > }
517
518 func (c *clientImpl) getClientForTaskQueuePartition(
519 partition tqid.Partition,
520 > ) (matchingservice.MatchingServiceClient, error) { client.go
521 > addr, err := c.Route(partition)
522 > if err != nil {
523 > return nil, err client.go
524 > }
525 client, err := c.clients.GetClientForClientKey(addr)
526 if err != nil {
go.temporal.io/server/service/worker/worker.go 57 covered LOC · 10 ranges

Open complete file

35 sdkClientFactory sdk.ClientFactory,
36 hostInfo membership.HostInfo,
37 > ) *workerManager { worker.go
38 > return &workerManager{
39 > hostInfo: hostInfo,
40 > logger: logger,
41 > sdkClientFactory: sdkClientFactory,
42 > workerComponents: workerComponents,
43 > }
44 > }
45
46 > func (wm *workerManager) Start() { worker.go
47 > if !atomic.CompareAndSwapInt32(
48 > &wm.status,
49 > common.DaemonStatusInitialized,
50 > common.DaemonStatusStarted,
51 > ) {
52 return
53 }
54
55 > defaultWorkerOptions := sdkworker.Options{ worker.go
56 > Identity: "temporal-system@" + wm.hostInfo.Identity(),
57 > // TODO: add dynamic config for worker options
58 > BackgroundActivityContext: headers.SetCallerType(context.Background(), headers.CallerTypeBackgroundHigh),
59 > }
60 > sdkClient := wm.sdkClientFactory.GetSystemClient()
61 > defaultWorker := wm.sdkClientFactory.NewWorker(sdkClient, primitives.DefaultWorkerTaskQueue, defaultWorkerOptions)
62 > wm.workers = []sdkworker.Worker{defaultWorker}
63 >
64 > for _, wc := range wm.workerComponents {
65 > wfWorkerOptions := wc.DedicatedWorkflowWorkerOptions()
66 > if wfWorkerOptions == nil {
67 > // use default worker
68 > wc.RegisterWorkflow(defaultWorker)
69 > } else {
70 wfWorkerOptions.Options.Identity = "temporal-system@" + wm.hostInfo.Identity()
71 // this worker component requires a dedicated worker
75 }
76
77 > activityWorkerOptions := wc.DedicatedActivityWorkerOptions() worker.go
78 > if activityWorkerOptions == nil {
79 // use default worker
80 wc.RegisterActivities(defaultWorker)
81 > } else { worker.go
82 > // TODO: This is to prevent issues during upgrade/downgrade. Remove in 1.24 release.
83 > wc.RegisterActivities(defaultWorker)
84 >
85 > // this worker component requires a dedicated worker for activities
86 > activityWorkerOptions.Options.DisableWorkflowWorker = true
87 > activityWorkerOptions.Options.Identity = "temporal-system@" + wm.hostInfo.Identity()
88 > activityWorker := wm.sdkClientFactory.NewWorker(sdkClient, activityWorkerOptions.TaskQueue, activityWorkerOptions.Options)
89 > wc.RegisterActivities(activityWorker)
90 > wm.workers = append(wm.workers, activityWorker)
91 > }
92 }
93
94 > for _, w := range wm.workers { worker.go
95 > if err := w.Start(); err != nil {
96 > wm.logger.Fatal("Unable to start worker", tag.Error(err)) worker.go
97 > }
98 }
99
100 > wm.logger.Info("", tag.ComponentWorkerManager, tag.LifeCycleStarted) worker.go
101 }
102
103 > func (wm *workerManager) Stop() { worker.go
104 > if !atomic.CompareAndSwapInt32(
105 > &wm.status,
106 > common.DaemonStatusStarted,
107 > common.DaemonStatusStopped,
108 > ) {
109 return
110 }
111
112 > for _, w := range wm.workers { worker.go
113 > w.Stop()
114 > }
115 > wm.logger.Info("", tag.ComponentWorkerManager, tag.LifeCycleStopped)
116 }
go.temporal.io/server/api/persistence/v1/hsm.pb.go 56 covered LOC · 13 ranges

Open complete file

147 func (*StateMachineMap) ProtoMessage() {}
148
149 > func (x *StateMachineMap) ProtoReflect() protoreflect.Message { hsm.pb.go
150 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[1]
151 > if x != nil {
152 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
153 if ms.LoadMessageInfo() == nil {
156 return ms
157 }
158 > return mi.MessageOf(x) hsm.pb.go
159 }
160
272 func (*StateMachineRef) ProtoMessage() {}
273
274 > func (x *StateMachineRef) ProtoReflect() protoreflect.Message { hsm.pb.go
275 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[3]
276 > if x != nil {
277 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
278 if ms.LoadMessageInfo() == nil {
281 return ms
282 }
283 > return mi.MessageOf(x) hsm.pb.go
284 }
285
349 func (*StateMachineTaskInfo) ProtoMessage() {}
350
351 > func (x *StateMachineTaskInfo) ProtoReflect() protoreflect.Message { hsm.pb.go
352 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[4]
353 > if x != nil {
354 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
355 if ms.LoadMessageInfo() == nil {
358 return ms
359 }
360 > return mi.MessageOf(x) hsm.pb.go
361 }
362
416 func (*StateMachineTimerGroup) ProtoMessage() {}
417
418 > func (x *StateMachineTimerGroup) ProtoReflect() protoreflect.Message { hsm.pb.go
419 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[5]
420 > if x != nil {
421 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
422 if ms.LoadMessageInfo() == nil {
425 return ms
426 }
427 > return mi.MessageOf(x) hsm.pb.go
428 }
429
478 func (*VersionedTransition) ProtoMessage() {}
479
480 > func (x *VersionedTransition) ProtoReflect() protoreflect.Message { hsm.pb.go
481 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[6]
482 > if x != nil {
483 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
484 if ms.LoadMessageInfo() == nil {
487 return ms
488 }
489 > return mi.MessageOf(x) hsm.pb.go
490 }
491
531 func (*StateMachineTombstoneBatch) ProtoMessage() {}
532
533 > func (x *StateMachineTombstoneBatch) ProtoReflect() protoreflect.Message { hsm.pb.go
534 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[7]
535 > if x != nil {
536 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
537 if ms.LoadMessageInfo() == nil {
540 return ms
541 }
542 > return mi.MessageOf(x) hsm.pb.go
543 }
544
895 }
896
897 > func init() { file_temporal_server_api_persistence_v1_hsm_proto_init() } hsm.pb.go
898 > func file_temporal_server_api_persistence_v1_hsm_proto_init() {
899 > if File_temporal_server_api_persistence_v1_hsm_proto != nil {
900 > return
901 > }
902 > file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[8].OneofWrappers = []any{
903 > (*StateMachineTombstone_ActivityScheduledEventId)(nil),
904 > (*StateMachineTombstone_TimerId)(nil),
905 > (*StateMachineTombstone_ChildExecutionInitiatedEventId)(nil),
906 > (*StateMachineTombstone_RequestCancelInitiatedEventId)(nil),
907 > (*StateMachineTombstone_SignalExternalInitiatedEventId)(nil),
908 > (*StateMachineTombstone_UpdateId)(nil),
909 > (*StateMachineTombstone_StateMachinePath)(nil),
910 > (*StateMachineTombstone_ChasmNodePath)(nil),
911 > }
912 > type x struct{}
913 > out := protoimpl.TypeBuilder{
914 > File: protoimpl.DescBuilder{
915 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
916 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_hsm_proto_rawDesc), len(file_temporal_server_api_persistence_v1_hsm_proto_rawDesc)),
917 > NumEnums: 0,
918 > NumMessages: 12,
919 > NumExtensions: 0,
920 > NumServices: 0,
921 > },
922 > GoTypes: file_temporal_server_api_persistence_v1_hsm_proto_goTypes,
923 > DependencyIndexes: file_temporal_server_api_persistence_v1_hsm_proto_depIdxs,
924 > MessageInfos: file_temporal_server_api_persistence_v1_hsm_proto_msgTypes,
925 > }.Build()
926 > File_temporal_server_api_persistence_v1_hsm_proto = out.File
927 > file_temporal_server_api_persistence_v1_hsm_proto_goTypes = nil
928 > file_temporal_server_api_persistence_v1_hsm_proto_depIdxs = nil
929 }
go.temporal.io/server/common/persistence/health_signal_aggregator.go 56 covered LOC · 17 ranges

Open complete file

60 latencyWindowSize time.Duration,
61 latencyWindowCount int,
62 > ) *healthSignalAggregatorImpl { health_signal_aggregator.go
63 > latencyDistribution, err := stats.NewWindowedTDigest(stats.WindowConfig{
64 > WindowSize: latencyWindowSize,
65 > WindowCount: latencyWindowCount,
66 > })
67 > if err != nil {
68 logger.Error("failed to create latency distribution helper, falling back to default config", tag.Error(err))
69 latencyDistribution, err = stats.NewWindowedTDigest(stats.WindowConfig{
76 }
77
78 > ret := &healthSignalAggregatorImpl{ health_signal_aggregator.go
79 > status: common.DaemonStatusInitialized,
80 > shutdownCh: make(chan struct{}),
81 > requestCounts: make(map[int32]int64),
82 > metricsHandler: metricsHandler,
83 > emitMetricsTimer: time.NewTicker(emitMetricsInterval),
84 > logger: logger,
85 > aggregationEnabled: aggregationEnabled,
86 > percentilesEnabled: percentilesEnabled,
87 > latencyDistribution: latencyDistribution,
88 > }
89 >
90 > if aggregationEnabled {
91 > ret.latencyAverage = aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize)
92 > ret.errorRatio = aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize)
93 > } else {
94 ret.latencyAverage = aggregate.NoopMovingWindowAverage
95 ret.errorRatio = aggregate.NoopMovingWindowAverage
96 }
97
98 > return ret health_signal_aggregator.go
99 }
100
101 > func (s *healthSignalAggregatorImpl) Start() { health_signal_aggregator.go
102 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
103 return
104 }
105 > go s.emitMetricsLoop() health_signal_aggregator.go
106 }
107
108 > func (s *healthSignalAggregatorImpl) Stop() { health_signal_aggregator.go
109 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
110 return
111 }
112 > close(s.shutdownCh) health_signal_aggregator.go
113 > s.emitMetricsTimer.Stop()
114 }
115
116 > func (s *healthSignalAggregatorImpl) Record(callerSegment int32, latency time.Duration, err error) { health_signal_aggregator.go
117 > if s.aggregationEnabled {
118 > s.latencyAverage.Record(latency.Milliseconds())
119 >
120 > if s.percentilesEnabled() && s.latencyDistribution != nil {
121 s.latencyDistribution.RecordToLatestWindow(float64(latency.Milliseconds()))
122 }
123
124 > if isUnhealthyError(err) { health_signal_aggregator.go
125 s.errorRatio.Record(1)
127 > s.errorRatio.Record(0) health_signal_aggregator.go
128 > }
129 }
130
131 > if callerSegment != CallerSegmentMissing { health_signal_aggregator.go
132 > s.incrementShardRequestCount(callerSegment)
133 > }
134 }
135
154 }
155
156 > func (s *healthSignalAggregatorImpl) incrementShardRequestCount(shardID int32) { health_signal_aggregator.go
157 > s.requestsLock.Lock()
158 > defer s.requestsLock.Unlock()
159 > s.requestCounts[shardID]++
160 > }
161
162 // Traverse through all shards and get the per-namespace persistence RPS for all shards.
164 // is configured in dynamic config. This will allow us to see if some namespaces had hit
165 // this limit in any of the shards.
166 > func (s *healthSignalAggregatorImpl) emitMetricsLoop() { health_signal_aggregator.go
167 > for {
168 > select {
169 > case <-s.shutdownCh: health_signal_aggregator.go
170 > return
171 case <-s.emitMetricsTimer.C:
172 s.requestsLock.Lock()
go.temporal.io/server/service/worker/workerdeployment/fx.go 54 covered LOC · 9 ranges

Open complete file

79 testHooks testhooks.TestHooks,
80 metricsHandler metrics.Handler,
81 > ) Client { fx.go
82 > highestRevSignaledToVersionWf := cache.New(dynamicconfig.ReactivationSignalDedupCacheMaxSize.Get(dc)(), nil)
83 > lc.Append(fx.Hook{
84 > OnStop: func(context.Context) error {
85 > highestRevSignaledToVersionWf.Stop() fx.go
86 > return nil
87 > },
88 })
89 > return &ClientImpl{ fx.go
90 > logger: logger,
91 > historyClient: historyClient,
92 > visibilityManager: visibilityManager,
93 > matchingClient: matchingClient,
94 > workerControllerInstanceClient: workerControllerInstanceClient,
95 > maxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
96 > visibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
97 > maxTaskQueuesInDeploymentVersion: dynamicconfig.MatchingMaxTaskQueuesInDeploymentVersion.Get(dc),
98 > maxDeployments: dynamicconfig.MatchingMaxDeployments.Get(dc),
99 > testHooks: testHooks,
100 > metricsHandler: metricsHandler,
101 > highestRevSignaledToVersionWf: highestRevSignaledToVersionWf,
102 > }
103 }
104
106 dc *dynamicconfig.Collection,
107 params activityDeps,
108 > ) fxResult { fx.go
109 > return fxResult{
110 > Component: &workerComponent{
111 > activityDeps: params,
112 > dynamicConfig: dc,
113 > },
114 > }
115 > }
116
117 > func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
118 > return &workercommon.PerNSDedicatedWorkerOptions{
119 > Enabled: true,
120 > }
121 > }
122
123 > func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, details workercommon.RegistrationDetails) func() { fx.go
124 > workflowVersionGetter := func() DeploymentWorkflowVersion {
125 val := DeploymentWorkflowVersion(dynamicconfig.MatchingDeploymentWorkflowVersion.Get(s.dynamicConfig)(ns.Name().String()))
126 return val
127 }
128
129 > versionWorkflow := func(ctx workflow.Context, args *deploymentspb.WorkerDeploymentVersionWorkflowArgs) error { fx.go
130 refreshIntervalGetter := func() time.Duration {
131 return dynamicconfig.VersionDrainageStatusRefreshInterval.Get(s.dynamicConfig)(ns.Name().String())
136 return VersionWorkflow(ctx, workflowVersionGetter, refreshIntervalGetter, visibilityGracePeriodGetter, args)
137 }
138 > registry.RegisterWorkflowWithOptions(versionWorkflow, workflow.RegisterOptions{Name: WorkerDeploymentVersionWorkflowType}) fx.go
139 >
140 > deploymentWorkflow := func(ctx workflow.Context, args *deploymentspb.WorkerDeploymentWorkflowArgs) error {
141 maxVersionsGetter := func() int {
142 return dynamicconfig.MatchingMaxVersionsInDeployment.Get(s.dynamicConfig)(ns.Name().String())
144 return Workflow(ctx, workflowVersionGetter, maxVersionsGetter, args)
145 }
146 > registry.RegisterWorkflowWithOptions(deploymentWorkflow, workflow.RegisterOptions{Name: WorkerDeploymentWorkflowType}) fx.go
147 >
148 > versionActivities := &VersionActivities{
149 > activityDeps: s.activityDeps,
150 > namespace: ns,
151 > }
152 > registry.RegisterActivity(versionActivities)
153 >
154 > activities := &Activities{
155 > activityDeps: s.activityDeps,
156 > namespace: ns,
157 > }
158 > registry.RegisterActivity(activities)
159 > return nil
160 }
go.temporal.io/server/common/archiver/archival_metadata.go 53 covered LOC · 10 ranges

Open complete file

47 )
48
49 > func (a *archivalConfig) StaticClusterState() ArchivalState { archival_metadata.go
50 > return a.staticClusterState
51 > }
52
53 const (
69 visibilityReadEnabled bool,
70 namespaceDefaults *config.ArchivalNamespaceDefaults,
71 > ) ArchivalMetadata { archival_metadata.go
72 > historyConfig := NewArchivalConfig(
73 > historyState,
74 > dynamicconfig.HistoryArchivalState.WithDefault(historyState).Get(dc),
75 > dynamicconfig.EnableReadFromHistoryArchival.WithDefault(historyReadEnabled).Get(dc),
76 > namespaceDefaults.History.State,
77 > namespaceDefaults.History.URI,
78 > )
79 >
80 > visibilityConfig := NewArchivalConfig(
81 > visibilityState,
82 > dynamicconfig.VisibilityArchivalState.WithDefault(visibilityState).Get(dc),
83 > dynamicconfig.EnableReadFromVisibilityArchival.WithDefault(visibilityReadEnabled).Get(dc),
84 > namespaceDefaults.Visibility.State,
85 > namespaceDefaults.Visibility.URI,
86 > )
87 >
88 > return &archivalMetadata{
89 > historyConfig: historyConfig,
90 > visibilityConfig: visibilityConfig,
91 > }
92 > }
93
94 > func (metadata *archivalMetadata) GetHistoryConfig() ArchivalConfig { archival_metadata.go
95 > return metadata.historyConfig
96 > }
97
98 > func (metadata *archivalMetadata) GetVisibilityConfig() ArchivalConfig { archival_metadata.go
99 > return metadata.visibilityConfig
100 > }
101
102 // NewArchivalConfig constructs a new valid ArchivalConfig
107 namespaceDefaultStateStr string,
108 namespaceDefaultURI string,
109 > ) ArchivalConfig { archival_metadata.go
110 > staticClusterState, err := getClusterArchivalState(staticClusterStateStr)
111 > if err != nil {
112 panic(err)
113 }
114 > namespaceDefaultState, err := getNamespaceArchivalState(namespaceDefaultStateStr) archival_metadata.go
115 > if err != nil {
116 panic(err)
117 }
118
119 > return &archivalConfig{ archival_metadata.go
120 > staticClusterState: staticClusterState,
121 > dynamicClusterState: dynamicClusterState,
122 > enableRead: enableRead,
123 > namespaceDefaultState: namespaceDefaultState,
124 > namespaceDefaultURI: namespaceDefaultURI,
125 > }
126 }
127
186 }
187
188 > func getClusterArchivalState(str string) (ArchivalState, error) { archival_metadata.go
189 > str = strings.TrimSpace(strings.ToLower(str))
190 > switch str {
191 > case "", config.ArchivalDisabled: archival_metadata.go
192 > return ArchivalDisabled, nil
193 case config.ArchivalPaused:
194 return ArchivalPaused, nil
199 }
200
201 > func getNamespaceArchivalState(str string) (enumspb.ArchivalState, error) { archival_metadata.go
202 > str = strings.TrimSpace(strings.ToLower(str))
203 > switch str {
204 > case "", config.ArchivalDisabled:
205 > return enumspb.ARCHIVAL_STATE_DISABLED, nil
206 case config.ArchivalEnabled:
207 return enumspb.ARCHIVAL_STATE_ENABLED, nil
go.temporal.io/server/service/history/shard/task_key_manager.go 53 covered LOC · 9 ranges

Open complete file

28 logger log.Logger,
29 renewRangeIDFn renewRangeIDFn,
30 > ) *taskKeyManager { task_key_manager.go
31 > return &taskKeyManager{
32 > generator: newTaskKeyGenerator(
33 > config.RangeSizeBits,
34 > timeSource,
35 > logger,
36 > renewRangeIDFn,
37 > ),
38 > tracker: newTaskRequestTracker(taskCategoryRegistry),
39 > timeSource: timeSource,
40 > logger: logger,
41 > config: config,
42 > }
43 > }
44
45 func (m *taskKeyManager) setAndTrackTaskKeys(
66 }
67
68 > func (m *taskKeyManager) drainTaskRequests() { task_key_manager.go
69 > m.tracker.drain()
70 > }
71
72 func (m *taskKeyManager) setRangeID(
73 rangeID int64,
75 > m.generator.setRangeID(rangeID)
76 >
77 > // rangeID update means all pending add tasks requests either already succeeded
78 > // are guaranteed to fail, so we can clear pending requests in the tracker
79 > m.tracker.clear()
80 > }
81
82 func (m *taskKeyManager) setTaskMinScheduledTime(
83 taskMinScheduledTime time.Time,
85 > m.generator.setTaskMinScheduledTime(taskMinScheduledTime)
86 > }
87
88 func (m *taskKeyManager) getExclusiveReaderHighWatermark(
89 category tasks.Category,
90 > ) tasks.Key { task_key_manager.go
91 > minTaskKey, ok := m.tracker.minTaskKey(category)
92 > if !ok {
93 > minTaskKey = tasks.MaximumKey task_key_manager.go
94 > }
95
96 // TODO: should this be moved generator.setTaskKeys() ?
97 > m.setTaskMinScheduledTime( task_key_manager.go
98 > // TODO: Truncation here is just to make sure task scheduled time has the same precision as the old logic.
99 > // Remove this truncation once we validate the rest of the code can worker correctly with higher precision.
100 > m.timeSource.Now().Add(m.config.TimerProcessorMaxTimeShift()).Truncate(common.ScheduledTaskMinPrecision),
101 > )
102 >
103 > nextTaskKey := m.generator.peekTaskKey(category)
104 >
105 > exclusiveReaderHighWatermark := tasks.MinKey(
106 > minTaskKey,
107 > nextTaskKey,
108 > )
109 > if category.Type() == tasks.CategoryTypeScheduled {
110 > exclusiveReaderHighWatermark.TaskID = 0 task_key_manager.go
111 >
112 > // TODO: Truncation here is just to make sure task scheduled time has the same precision as the old logic.
113 > // Remove this truncation once we validate the rest of the code can worker correctly with higher precision.
114 > exclusiveReaderHighWatermark.FireTime = exclusiveReaderHighWatermark.FireTime.
115 > Truncate(common.ScheduledTaskMinPrecision)
116 > }
117
118 > return exclusiveReaderHighWatermark task_key_manager.go
119 }
go.temporal.io/server/service/history/queues/reader_group.go 51 covered LOC · 15 ranges

Open complete file

30 func NewReaderGroup(
31 initializer ReaderInitializer,
32 > ) *ReaderGroup { reader_group.go
33 > return &ReaderGroup{
34 > initializer: initializer,
35 >
36 > status: common.DaemonStatusInitialized,
37 > readerMap: make(map[int64]Reader),
38 > }
39 > }
40
41 > func (g *ReaderGroup) Start() { reader_group.go
42 > if !atomic.CompareAndSwapInt32(&g.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
43 return
44 }
45
46 > g.Lock() reader_group.go
47 > defer g.Unlock()
48 >
49 > for _, reader := range g.readerMap {
50 reader.Start()
51 }
52 }
53
54 > func (g *ReaderGroup) Stop() { reader_group.go
55 > if !atomic.CompareAndSwapInt32(&g.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
56 return
57 }
58
59 > g.Lock() reader_group.go
60 > defer g.Unlock()
61 >
62 > for _, reader := range g.readerMap {
63 > reader.Stop() reader_group.go
64 > }
65 }
66
100 }
101
102 > func (g *ReaderGroup) ReaderByID(readerID int64) (Reader, bool) { reader_group.go
103 > g.Lock()
104 > defer g.Unlock()
105 >
106 > return g.getReaderByIDLocked(readerID)
107 > }
108
109 > func (g *ReaderGroup) getReaderByIDLocked(readerID int64) (Reader, bool) { reader_group.go
110 > if g.readerMap == nil {
111 return nil, false
112 }
113
114 > reader, ok := g.readerMap[readerID] reader_group.go
115 > return reader, ok
116 }
117
118 > func (g *ReaderGroup) NewReader(readerID int64, slices ...Slice) Reader { reader_group.go
119 > g.Lock()
120 > defer g.Unlock()
121 >
122 > return g.newReaderLocked(readerID, slices...)
123 > }
124
125 > func (g *ReaderGroup) newReaderLocked(readerID int64, slices ...Slice) Reader { reader_group.go
126 > reader := g.initializer(readerID, slices)
127 >
128 > if _, ok := g.readerMap[readerID]; ok {
129 panic(fmt.Sprintf("reader with ID %v already exists", readerID))
130 }
131
132 > g.readerMap[readerID] = reader reader_group.go
133 >
134 > if g.isStarted() {
135 > reader.Start() reader_group.go
136 > }
137 > return reader reader_group.go
138 }
139
151 }
152
153 > func (g *ReaderGroup) isStarted() bool { reader_group.go
154 > return atomic.LoadInt32(&g.status) == common.DaemonStatusStarted
155 > }
go.temporal.io/server/common/backoff/retry.go 50 covered LOC · 21 ranges

Open complete file

39 // ThrottleRetry is a resource aware version of Retry.
40 // Resource exhausted error will be retried using a different throttle retry policy, instead of the specified one.
41 > func ThrottleRetry(operation Operation, policy RetryPolicy, isRetryable IsRetryable) error { retry.go
42 > ctxOp := func(context.Context) error { return operation() }
43 > return ThrottleRetryContext(context.Background(), ctxOp, policy, isRetryable)
44 }
45
53 policy RetryPolicy,
54 isRetryable IsRetryable,
55 > ) error { retry.go
56 > var err error
57 > var next time.Duration
58 >
59 > if isRetryable == nil {
60 > isRetryable = func(error) bool { return true } retry.go
61 }
62
63 > deadline, hasDeadline := ctx.Deadline() retry.go
64 >
65 > timeSrc := clock.NewRealTimeSource()
66 > r := NewRetrier(policy, timeSrc)
67 > t := NewRetrier(throttleRetryPolicy, timeSrc)
68 > for ctx.Err() == nil {
69 > if err = operation(ctx); err == nil { retry.go
70 > return nil retry.go
71 > }
72
73 > if next = r.NextBackOff(err); next == done { retry.go
74 return err
75 }
76
77 > if err == ctx.Err() || !isRetryable(err) { retry.go
78 > return err retry.go
79 > }
80
81 > if _, ok := err.(*serviceerror.ResourceExhausted); ok { retry.go
82 next = max(next, t.NextBackOff(err))
83 }
84
85 > if hasDeadline && timeSrc.Now().Add(next).After(deadline) { retry.go
86 break
87 }
88
89 > timer := time.NewTimer(next) retry.go
90 > select {
91 case <-timer.C:
92 > case <-ctx.Done(): retry.go
93 > timer.Stop()
94 }
95 }
96 // always return the last error we got from operation, even if it is not useful
97 // this retry utility does not have enough information to do any filtering/mapping
98 > if err != nil { retry.go
99 > return err retry.go
100 > }
101 return ctx.Err()
102 }
111 policy RetryPolicy,
112 isRetryable IsRetryable,
113 > ) (T, error) { retry.go
114 > var zero T
115 > var result T
116 > var err error
117 > var next time.Duration
118 >
119 > if isRetryable == nil {
120 isRetryable = func(error) bool { return true }
121 }
122
123 > deadline, hasDeadline := ctx.Deadline() retry.go
124 >
125 > timeSrc := clock.NewRealTimeSource()
126 > r := NewRetrier(policy, timeSrc)
127 > t := NewRetrier(throttleRetryPolicy, timeSrc)
128 > for ctx.Err() == nil {
129 > result, err = fn(ctx) retry.go
130 > if err == nil {
131 return result, nil
132 }
133
134 > if next = r.NextBackOff(err); next == done { retry.go
135 return zero, err
136 }
137
138 > if err == ctx.Err() || !isRetryable(err) { retry.go
139 > return zero, err retry.go
140 > }
141
142 if _, ok := err.(*serviceerror.ResourceExhausted); ok {
go.temporal.io/server/common/persistence/sql/queue.go 50 covered LOC · 16 ranges

Open complete file

27 queueType persistence.QueueType,
28 serializer serialization.Serializer,
29 > ) (persistence.Queue, error) { queue.go
30 > queue := &sqlQueue{
31 > SqlStore: NewSQLStore(db, logger, serializer),
32 > queueType: queueType,
33 > logger: logger,
34 > }
35 > return queue, nil
36 > }
37
38 func (q *sqlQueue) Init(
39 ctx context.Context,
40 blob *commonpb.DataBlob,
41 > ) error { queue.go
42 > if err := q.initializeQueueMetadata(ctx, blob); err != nil {
43 return err
44 }
45 > return q.initializeDLQMetadata(ctx, blob) queue.go
46 }
47
309 }
310
311 > func (q *sqlQueue) getDLQTypeFromQueueType() persistence.QueueType { queue.go
312 > return -q.queueType
313 > }
314
315 func (q *sqlQueue) initializeQueueMetadata(
316 ctx context.Context,
317 blob *commonpb.DataBlob,
318 > ) error { queue.go
319 > _, err := q.DB.SelectFromQueueMetadata(ctx, sqlplugin.QueueMetadataFilter{
320 > QueueType: q.queueType,
321 > })
322 > switch err {
323 > case nil: queue.go
324 > return nil
325 > case sql.ErrNoRows: queue.go
326 > result, err := q.DB.InsertIntoQueueMetadata(ctx, &sqlplugin.QueueMetadataRow{
327 > QueueType: q.queueType,
328 > Data: blob.Data,
329 > DataEncoding: blob.EncodingType.String(),
330 > })
331 > if err != nil {
332 return serviceerror.NewUnavailablef("initializeQueueMetadata operation failed. Error %v", err)
333 }
334 > rowsAffected, err := result.RowsAffected() queue.go
335 > if err != nil {
336 return fmt.Errorf("rowsAffected returned error when initializing queue metadata %v: %v", q.queueType, err)
337 }
338 > if rowsAffected != 1 { queue.go
339 return fmt.Errorf("rowsAffected returned %v queue metadata instead of one", rowsAffected)
340 }
341 > return nil queue.go
342 default:
343 return err
348 ctx context.Context,
349 blob *commonpb.DataBlob,
350 > ) error { queue.go
351 > _, err := q.DB.SelectFromQueueMetadata(ctx, sqlplugin.QueueMetadataFilter{
352 > QueueType: q.getDLQTypeFromQueueType(),
353 > })
354 > switch err {
355 > case nil: queue.go
356 > return nil
357 > case sql.ErrNoRows: queue.go
358 > result, err := q.DB.InsertIntoQueueMetadata(ctx, &sqlplugin.QueueMetadataRow{
359 > QueueType: q.getDLQTypeFromQueueType(),
360 > Data: blob.Data,
361 > DataEncoding: blob.EncodingType.String(),
362 > })
363 > if err != nil {
364 return serviceerror.NewUnavailablef("initializeDLQMetadata operation failed. Error %v", err)
365 }
366 > rowsAffected, err := result.RowsAffected() queue.go
367 > if err != nil {
368 return fmt.Errorf("rowsAffected returned error when initializing DLQ metadata %v: %v", q.queueType, err)
369 }
370 > if rowsAffected != 1 { queue.go
371 return fmt.Errorf("rowsAffected returned %v DLQ metadata instead of one", rowsAffected)
372 }
373 > return nil queue.go
374 default:
375 return err
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/execution.go 50 covered LOC · 9 ranges

Open complete file

464 ctx context.Context,
465 filter sqlplugin.HistoryImmediateTasksRangeFilter,
466 > ) ([]sqlplugin.HistoryImmediateTasksRow, error) { execution.go
467 > var rows []sqlplugin.HistoryImmediateTasksRow
468 > if err := mdb.conn.SelectContext(ctx,
469 > &rows,
470 > getHistoryImmediateTasksQuery,
471 > filter.ShardID,
472 > filter.CategoryID,
473 > filter.InclusiveMinTaskID,
474 > filter.ExclusiveMaxTaskID,
475 > filter.PageSize,
476 > ); err != nil {
477 return nil, err
478 }
479 > return rows, nil execution.go
480 }
481
595 ctx context.Context,
596 filter sqlplugin.TransferTasksRangeFilter,
597 > ) ([]sqlplugin.TransferTasksRow, error) { execution.go
598 > var rows []sqlplugin.TransferTasksRow
599 > if err := mdb.conn.SelectContext(ctx,
600 > &rows,
601 > getTransferTasksQuery,
602 > filter.ShardID,
603 > filter.InclusiveMinTaskID,
604 > filter.ExclusiveMaxTaskID,
605 > filter.PageSize,
606 > ); err != nil {
607 return nil, err
608 }
609 > return rows, nil execution.go
610 }
611
654 ctx context.Context,
655 filter sqlplugin.TimerTasksRangeFilter,
656 > ) ([]sqlplugin.TimerTasksRow, error) { execution.go
657 > var rows []sqlplugin.TimerTasksRow
658 > filter.InclusiveMinVisibilityTimestamp = mdb.converter.ToSQLiteDateTime(filter.InclusiveMinVisibilityTimestamp)
659 > filter.ExclusiveMaxVisibilityTimestamp = mdb.converter.ToSQLiteDateTime(filter.ExclusiveMaxVisibilityTimestamp)
660 > if err := mdb.conn.SelectContext(ctx,
661 > &rows,
662 > getTimerTasksQuery,
663 > filter.ShardID,
664 > filter.InclusiveMinVisibilityTimestamp,
665 > filter.InclusiveMinTaskID,
666 > filter.InclusiveMinVisibilityTimestamp,
667 > filter.ExclusiveMaxVisibilityTimestamp,
668 > filter.PageSize,
669 > ); err != nil {
670 return nil, err
671 }
672 > for i := range rows { execution.go
673 rows[i].VisibilityTimestamp = mdb.converter.FromSQLiteDateTime(rows[i].VisibilityTimestamp)
674 }
675 > return rows, nil execution.go
676 }
677
880 ctx context.Context,
881 filter sqlplugin.VisibilityTasksRangeFilter,
882 > ) ([]sqlplugin.VisibilityTasksRow, error) { execution.go
883 > var rows []sqlplugin.VisibilityTasksRow
884 > if err := mdb.conn.SelectContext(ctx,
885 > &rows,
886 > getVisibilityTasksQuery,
887 > filter.ShardID,
888 > filter.InclusiveMinTaskID,
889 > filter.ExclusiveMaxTaskID,
890 > filter.PageSize,
891 > ); err != nil {
892 return nil, err
893 }
894 > return rows, nil execution.go
895 }
896
go.temporal.io/server/common/tqid/task_queue_id.go 49 covered LOC · 18 ranges

Open complete file

211 }
212
213 > func NormalPartitionFromRpcName(rpcName string, namespaceId string, taskType enumspb.TaskQueueType) (*NormalPartition, error) { task_queue_id.go
214 > baseName, partition, err := parseRpcName(rpcName)
215 > if err != nil {
216 return nil, err
217 }
218 > tq := &TaskQueue{TaskQueueFamily{namespaceId, baseName}, taskType} task_queue_id.go
219 > return tq.NormalPartition(partition), nil
220 }
221
222 > func MustNormalPartitionFromRpcName(rpcName string, namespaceId string, taskType enumspb.TaskQueueType) *NormalPartition { task_queue_id.go
223 > p, err := NormalPartitionFromRpcName(rpcName, namespaceId, taskType)
224 > if err != nil {
225 panic(err)
226 }
227 > return p task_queue_id.go
228 }
229
230 > func (n *TaskQueueFamily) Name() string { task_queue_id.go
231 > return n.name
232 > }
233
234 func (n *TaskQueueFamily) NamespaceId() string {
259 }
260
261 > func (n *TaskQueue) NormalPartition(partitionId int) *NormalPartition { task_queue_id.go
262 > return &NormalPartition{
263 > taskQueue: n,
264 > partitionId: partitionId,
265 > }
266 > }
267
268 func (n *TaskQueue) StickyPartition(stickyName string) *StickyPartition {
388 }
389
390 > func (p *NormalPartition) TaskQueue() *TaskQueue { task_queue_id.go
391 > return p.taskQueue
392 > }
393
394 > func (p *NormalPartition) IsRoot() bool { task_queue_id.go
395 > return p.partitionId == 0
396 > }
397
398 func (p *NormalPartition) IsChild() bool {
419 }
420
421 > func (p *NormalPartition) NamespaceId() string { task_queue_id.go
422 > return p.taskQueue.family.namespaceId
423 > }
424
425 > func (p *NormalPartition) TaskType() enumspb.TaskQueueType { task_queue_id.go
426 > return p.taskQueue.taskType
427 > }
428
429 // ParentPartition returns a NormalPartition for the parent partition, using the given branching degree.
438 }
439
440 > func (p *NormalPartition) RpcName() string { task_queue_id.go
441 > if p.IsRoot() {
442 > return p.TaskQueue().family.Name() task_queue_id.go
443 > }
444 return nonRootPartitionPrefix + p.TaskQueue().Name() + partitionDelimiter + strconv.Itoa(p.partitionId)
445 }
454 }
455
456 > func (p *NormalPartition) RoutingKey(batchSize int) (string, int) { task_queue_id.go
457 > if batchSize == 0 {
458 > return fmt.Sprintf("%s:%s:%d", p.NamespaceId(), p.RpcName(), p.TaskType()), 0 task_queue_id.go
459 > }
460 // We want to use LookupN to spread partitions across available nodes, but LookupN takes O(n)
461 // time and space, so we should limit the n that we pass to it. Reduce the partition id by some
472 }
473
474 > func (p *NormalPartition) GradualChangeKey() []byte { task_queue_id.go
475 > key := fmt.Sprintf("%s:%s:%d", p.NamespaceId(), p.RpcName(), p.TaskType())
476 > return []byte(key)
477 > }
478
479 // parseRpcName takes the rpc name of a task queue partition and returns a ParseTaskQueuePartition.
480 // Returns an error if the given name is not a valid rpc name.
481 > func parseRpcName(rpcName string) (string, int, error) { task_queue_id.go
482 > baseName := rpcName
483 > partition := 0
484 >
485 > if strings.HasPrefix(rpcName, nonRootPartitionPrefix) {
486 suffixOff := strings.LastIndex(rpcName, partitionDelimiter)
487 if suffixOff <= len(nonRootPartitionPrefix) {
498 }
499
500 > if strings.HasPrefix(baseName, nonRootPartitionPrefix) { task_queue_id.go
501 return "", 0, serviceerror.NewInvalidArgument("task queue family name cannot have prefix /_sys/ " + baseName)
502 }
503 > return baseName, partition, nil task_queue_id.go
504 }
go.temporal.io/server/service/frontend/configs/quotas.go 49 covered LOC · 12 ranges

Open complete file

274 namespaceReplicationInducingRateBurstFn quotas.RateBurst,
275 operatorRPSRatio dynamicconfig.FloatPropertyFn,
276 > ) quotas.RequestRateLimiter { quotas.go
277 > mapping := make(map[string]quotas.RequestRateLimiter)
278 >
279 > executionRateLimiter := NewExecutionPriorityRateLimiter(executionRateBurstFn, operatorRPSRatio)
280 > visibilityRateLimiter := NewVisibilityPriorityRateLimiter(visibilityRateBurstFn, operatorRPSRatio)
281 > namespaceReplicationInducingRateLimiter := NewNamespaceReplicationInducingAPIPriorityRateLimiter(namespaceReplicationInducingRateBurstFn, operatorRPSRatio)
282 >
283 > for api := range APIToPriority {
284 > mapping[api] = executionRateLimiter
285 > }
286 > for api := range VisibilityAPIToPriority {
287 > mapping[api] = visibilityRateLimiter
288 > }
289 > for api := range NamespaceReplicationInducingAPIToPriority {
290 > mapping[api] = namespaceReplicationInducingRateLimiter
291 > }
292
293 > return quotas.NewRoutingRateLimiter(mapping) quotas.go
294 }
295
297 rateBurstFn quotas.RateBurst,
298 operatorRPSRatio dynamicconfig.FloatPropertyFn,
299 > ) quotas.RequestRateLimiter { quotas.go
300 > return quotas.NewPriorityRateLimiterHelper(
301 > rateBurstFn,
302 > operatorRPSRatio,
303 > func(req quotas.Request) int {
304 > if req.CallerType == headers.CallerTypeOperator { quotas.go
305 return quotas.OperatorPriority
306 }
307 > if priority, ok := APIToPriority[req.API]; ok { quotas.go
308 > return priority quotas.go
309 > }
310 return ExecutionAPIPrioritiesOrdered[len(ExecutionAPIPrioritiesOrdered)-1]
311 },
317 rateBurstFn quotas.RateBurst,
318 operatorRPSRatio dynamicconfig.FloatPropertyFn,
319 > ) quotas.RequestRateLimiter { quotas.go
320 > return quotas.NewPriorityRateLimiterHelper(
321 > rateBurstFn,
322 > operatorRPSRatio,
323 > func(req quotas.Request) int {
324 if req.CallerType == headers.CallerTypeOperator {
325 return quotas.OperatorPriority
337 rateBurstFn quotas.RateBurst,
338 operatorRPSRatio dynamicconfig.FloatPropertyFn,
339 > ) quotas.RequestRateLimiter { quotas.go
340 > return quotas.NewPriorityRateLimiterHelper(
341 > rateBurstFn,
342 > operatorRPSRatio,
343 > func(req quotas.Request) int {
344 if req.CallerType == headers.CallerTypeOperator {
345 return quotas.OperatorPriority
361 globalQuotaBurstRatio dynamicconfig.FloatPropertyFnWithNamespaceFilter,
362 logger log.Logger,
363 > ) quotas.RequestRateLimiter { quotas.go
364 > rateFn := calculator.NewLoggedNamespaceCalculator(
365 > calculator.ClusterAwareNamespaceQuotaCalculator{
366 > MemberCounter: memberCounter,
367 > PerInstanceQuota: func(ns string) int { return 0 },
368 GlobalQuota: globalQuota,
369 },
371 ).GetQuota
372
373 > return quotas.NewNamespaceRequestRateLimiter( quotas.go
374 > func(req quotas.Request) quotas.RequestRateLimiter {
375 return quotas.NewRequestRateLimiterAdapter(
376 quotas.NewDynamicRateLimiter(
386 }
387
388 > func IsAPIOperation(apiFullName string) bool { quotas.go
389 > if _, ok := operationExcludedAPIs[apiFullName]; ok {
390 return false
391 }
392
393 > _, inAPI := APIToPriority[apiFullName] quotas.go
394 > _, inNamespaceReplicationInducingAPI := NamespaceReplicationInducingAPIToPriority[apiFullName]
395 >
396 > return inAPI || inNamespaceReplicationInducingAPI
397 }
go.temporal.io/server/service/history/queues/rescheduler.go 49 covered LOC · 10 ranges

Open complete file

75 logger log.Logger,
76 metricsHandler metrics.Handler,
77 > ) *reschedulerImpl { rescheduler.go
78 > return &reschedulerImpl{
79 > scheduler: scheduler,
80 > timeSource: timeSource,
81 > logger: logger,
82 > metricsHandler: metricsHandler,
83 >
84 > status: common.DaemonStatusInitialized,
85 > shutdownCh: make(chan struct{}),
86 >
87 > timerGate: timer.NewLocalGate(timeSource),
88 > taskChannelKeyFn: scheduler.TaskChannelKeyFn(),
89 >
90 > pqMap: make(map[TaskChannelKey]collection.Queue[rescheduledExecuable]),
91 > }
92 > }
93
94 > func (r *reschedulerImpl) Start() { rescheduler.go
95 > if !atomic.CompareAndSwapInt32(&r.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
96 return
97 }
98
99 > r.shutdownWG.Add(1) rescheduler.go
100 > go r.rescheduleLoop()
101 >
102 > r.logger.Info("Task rescheduler started.", tag.LifeCycleStarted)
103 }
104
105 > func (r *reschedulerImpl) Stop() { rescheduler.go
106 > if !atomic.CompareAndSwapInt32(&r.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
107 return
108 }
109
110 > close(r.shutdownCh) rescheduler.go
111 > r.timerGate.Close()
112 >
113 > if success := common.AwaitWaitGroup(&r.shutdownWG, time.Minute); !success {
114 r.logger.Warn("Task rescheduler timedout on shutdown.", tag.LifeCycleStopTimedout)
115 }
116
117 > r.logger.Info("Task rescheduler stopped.", tag.LifeCycleStopped) rescheduler.go
118 }
119
179 }
180
181 > func (r *reschedulerImpl) rescheduleLoop() { rescheduler.go
182 > defer r.shutdownWG.Done()
183 >
184 > cleanupTimer := time.NewTimer(backoff.Jitter(
185 > reschedulerPQCleanupDuration,
186 > reschedulerPQCleanupJitterCoefficient,
187 > ))
188 > defer cleanupTimer.Stop()
189 >
190 > for {
191 > select {
192 > case <-r.shutdownCh: rescheduler.go
193 > r.drain()
194 > return
195 case <-r.timerGate.FireCh():
196 r.reschedule()
252 }
253
254 > func (r *reschedulerImpl) drain() { rescheduler.go
255 > r.Lock()
256 > defer r.Unlock()
257 >
258 > for key, pq := range r.pqMap {
259 for !pq.IsEmpty() {
260 pq.Remove()
go.temporal.io/server/common/persistence/shard_manager.go 48 covered LOC · 13 ranges

Open complete file

19 shardStore ShardStore,
20 serializer serialization.Serializer,
21 > ) ShardManager { shard_manager.go
22 > return &shardManagerImpl{
23 > shardStore: shardStore,
24 > serializer: serializer,
25 > }
26 > }
27
28 > func (m *shardManagerImpl) Close() { shard_manager.go
29 > m.shardStore.Close()
30 > }
31
32 func (m *shardManagerImpl) GetName() string {
37 ctx context.Context,
38 request *GetOrCreateShardRequest,
39 > ) (*GetOrCreateShardResponse, error) { shard_manager.go
40 > createShardInfo := func() (int64, *commonpb.DataBlob, error) {
41 > shardInfo := request.InitialShardInfo shard_manager.go
42 > if shardInfo == nil {
43 > shardInfo = &persistencespb.ShardInfo{} shard_manager.go
44 > }
45 > shardInfo.ShardId = request.ShardID shard_manager.go
46 > shardInfo.UpdateTime = timestamp.TimeNowPtrUtc()
47 > data, err := m.serializer.ShardInfoToBlob(shardInfo)
48 > if err != nil {
49 return 0, nil, err
50 }
51 > return shardInfo.GetRangeId(), data, nil shard_manager.go
52 }
53 > internalResp, err := m.shardStore.GetOrCreateShard(ctx, &InternalGetOrCreateShardRequest{ shard_manager.go
54 > ShardID: request.ShardID,
55 > CreateShardInfo: createShardInfo,
56 > LifecycleContext: request.LifecycleContext,
57 > })
58 > if err != nil {
59 return nil, err
60 }
61 > shardInfo, err := m.serializer.ShardInfoFromBlob(internalResp.ShardInfo) shard_manager.go
62 > if err != nil {
63 return nil, err
64 }
65 > return &GetOrCreateShardResponse{ shard_manager.go
66 > ShardInfo: shardInfo,
67 > }, nil
68 }
69
71 ctx context.Context,
72 request *UpdateShardRequest,
73 > ) error { shard_manager.go
74 > shardInfo := request.ShardInfo
75 > shardInfo.UpdateTime = timestamp.TimeNowPtrUtc()
76 >
77 > shardInfoBlob, err := m.serializer.ShardInfoToBlob(shardInfo)
78 > if err != nil {
79 return err
80 }
81 > internalRequest := &InternalUpdateShardRequest{ shard_manager.go
82 > ShardID: request.ShardInfo.GetShardId(),
83 > RangeID: request.ShardInfo.GetRangeId(),
84 > Owner: request.ShardInfo.GetOwner(),
85 > ShardInfo: shardInfoBlob,
86 > PreviousRangeID: request.PreviousRangeID,
87 > }
88 > return m.shardStore.UpdateShard(ctx, internalRequest)
89 }
90
92 ctx context.Context,
93 request *AssertShardOwnershipRequest,
94 > ) error { shard_manager.go
95 > return m.shardStore.AssertShardOwnership(ctx, request)
96 > }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/db.go 48 covered LOC · 13 ranges

Open complete file

39 tx *sqlx.Tx,
40 logger log.Logger,
41 > ) *db { db.go
42 > mdb := &db{
43 > dbKind: dbKind,
44 > dbName: dbName,
45 > onClose: make([]func(), 0),
46 > db: xdb,
47 > tx: tx,
48 > logger: logger,
49 > }
50 > mdb.conn = xdb
51 > if tx != nil {
52 > mdb.conn = tx db.go
53 > }
54 > mdb.converter = &converter{} db.go
55 > return mdb
56 }
57
58 // BeginTx starts a new transaction and returns a reference to the Tx object
59 > func (mdb *db) BeginTx(ctx context.Context) (sqlplugin.Tx, error) { db.go
60 > xtx, err := mdb.db.BeginTxx(ctx, nil)
61 > if err != nil {
62 return nil, err
63 }
64 > return newDB(mdb.dbKind, mdb.dbName, mdb.db, xtx, mdb.logger), nil db.go
65 }
66
67 // Commit commits a previously started transaction
68 > func (mdb *db) Commit() error { db.go
69 > return mdb.tx.Commit()
70 > }
71
72 // Rollback triggers rollback of a previously started transaction
75 }
76
77 > func (mdb *db) OnClose(hook func()) { db.go
78 > mdb.mu.Lock()
79 > mdb.onClose = append(mdb.onClose, hook)
80 > mdb.mu.Unlock()
81 > }
82
83 // Close closes the connection to the sqlite db
84 > func (mdb *db) Close() error { db.go
85 > mdb.mu.RLock()
86 > defer mdb.mu.RUnlock()
87 >
88 > for _, hook := range mdb.onClose {
89 > // de-registers the database from conn pool db.go
90 > hook()
91 > }
92
93 // database connection will be automatically closed by the hook handler when all references are removed
94 > return nil db.go
95 }
96
97 // PluginName returns the name of the plugin
98 > func (mdb *db) PluginName() string { db.go
99 > return PluginName
100 > }
101
102 // DbName returns the name of the database
103 > func (mdb *db) DbName() string { db.go
104 > return mdb.dbName
105 > }
106
107 // ExpectedVersion returns expected version.
118
119 // VerifyVersion verify schema version is up to date
120 > func (mdb *db) VerifyVersion() error { db.go
121 > return nil
122 > // TODO(jlegrone): implement this
123 > // expectedVersion := mdb.ExpectedVersion()
124 > // return schema.VerifyCompatibleVersion(mdb, mdb.dbName, expectedVersion)
125 > }
go.temporal.io/server/service/worker/batcher/fx.go 48 covered LOC · 5 ranges

Open complete file

63 serviceResolver membership.ServiceResolver,
64 logger log.Logger,
65 > ) AdminBatcherRateLimiter { fx.go
66 > return quotas.NewRequestRateLimiterAdapter(
67 > quotas.NewDefaultOutgoingRateLimiter(
68 > calculator.NewLoggedCalculator(
69 > calculator.ClusterAwareQuotaCalculator{
70 > MemberCounter: serviceResolver,
71 > PerInstanceQuota: dynamicconfig.AdminBatcherHostRPS.Get(dc),
72 > GlobalQuota: dynamicconfig.AdminBatcherGlobalRPS.Get(dc),
73 > },
74 > log.With(logger, tag.ComponentAdminBatcher, tag.ScopeHost),
75 > ).GetQuota,
76 > ),
77 > )
78 > }
79
80 func NewResult(
81 dc *dynamicconfig.Collection,
82 params activityDeps,
83 > ) fxResult { fx.go
84 > return fxResult{
85 > Component: &workerComponent{
86 > activityDeps: params,
87 > dc: dc,
88 > enabledFeature: dynamicconfig.EnableBatcherNamespace.Get(dc),
89 > },
90 > }
91 > }
92
93 > func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
94 > namespaceName := ns.Name().String()
95 > enableFeature := s.enabledFeature(namespaceName)
96 > return &workercommon.PerNSDedicatedWorkerOptions{
97 > Enabled: enableFeature,
98 > }
99 > }
100
101 > func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, _ workercommon.RegistrationDetails) func() { fx.go
102 > // Register the batch workflow with both the proto-qualified and unqualified types.
103 > // TODO(spkane31): Remove the proto-qualified type and call the unqualified type from the frontend after the 1.30 release.
104 > registry.RegisterWorkflowWithOptions(BatchWorkflowProtobuf, workflow.RegisterOptions{Name: BatchWFTypeName})
105 > // Newer version of the batch workflow which was rewritten to accept a proto struct as input.
106 > registry.RegisterWorkflowWithOptions(BatchWorkflowProtobuf, workflow.RegisterOptions{Name: BatchWFTypeProtobufName})
107 > registry.RegisterActivity(s.activities(ns.Name(), ns.ID()))
108 > return nil
109 > }
110
111 > func (s *workerComponent) activities(name namespace.Name, id namespace.ID) *activities { fx.go
112 > return &activities{
113 > activityDeps: s.activityDeps,
114 > namespace: name,
115 > namespaceID: id,
116 > rps: dynamicconfig.BatcherRPS.Get(s.dc),
117 > concurrency: dynamicconfig.BatcherConcurrency.Get(s.dc),
118 > }
119 > }
go.temporal.io/server/common/metrics/defs.go 47 covered LOC · 9 ranges

Open complete file

20 )
21
22 > func NewTimerDef(name string, opts ...Option) timerDefinition { defs.go
23 > // This line cannot be combined with others!
24 > // This ensures the stack trace has information of the caller.
25 > def := newMetricDefinition(name, opts...)
26 > globalRegistry.register(def)
27 > return timerDefinition{def}
28 > }
29
30 > func NewBytesHistogramDef(name string, opts ...Option) histogramDefinition { defs.go
31 > // This line cannot be combined with others!
32 > // This ensures the stack trace has information of the caller.
33 > def := newMetricDefinition(name, append(opts, WithUnit(Bytes))...)
34 > globalRegistry.register(def)
35 > return histogramDefinition{def}
36 > }
37
38 > func NewDimensionlessHistogramDef(name string, opts ...Option) histogramDefinition { defs.go
39 > // This line cannot be combined with others!
40 > // This ensures the stack trace has information of the caller.
41 > def := newMetricDefinition(name, append(opts, WithUnit(Dimensionless))...)
42 > globalRegistry.register(def)
43 > return histogramDefinition{def}
44 > }
45
46 > func NewCounterDef(name string, opts ...Option) counterDefinition { defs.go
47 > // This line cannot be combined with others!
48 > // This ensures the stack trace has information of the caller.
49 > def := newMetricDefinition(name, opts...)
50 > globalRegistry.register(def)
51 > return counterDefinition{def}
52 > }
53
54 > func NewGaugeDef(name string, opts ...Option) gaugeDefinition { defs.go
55 > // This line cannot be combined with others!
56 > // This ensures the stack trace has information of the caller.
57 > def := newMetricDefinition(name, opts...)
58 > globalRegistry.register(def)
59 > return gaugeDefinition{def}
60 > }
61
62 > func (d histogramDefinition) With(handler Handler) HistogramIface { defs.go
63 > return handler.Histogram(d.name, d.unit)
64 > }
65
66 > func (d counterDefinition) With(handler Handler) CounterIface { defs.go
67 > return handler.Counter(d.name)
68 > }
69
70 > func (d gaugeDefinition) With(handler Handler) GaugeIface { defs.go
71 > return handler.Gauge(d.name)
72 > }
73
74 > func (d timerDefinition) With(handler Handler) TimerIface { defs.go
75 > return handler.Timer(d.name)
76 > }
go.temporal.io/server/common/quotas/dynamic_rate_limiter_impl.go 47 covered LOC · 10 ranges

Open complete file

29 rateBurstFn RateBurst,
30 refreshInterval time.Duration,
31 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
32 > rateLimiter := &DynamicRateLimiterImpl{
33 > rateBurstFn: rateBurstFn,
34 > refreshInterval: refreshInterval,
35 >
36 > refreshTimer: time.NewTimer(refreshInterval),
37 > rateLimiter: NewRateLimiter(rateBurstFn.Rate(), rateBurstFn.Burst()),
38 > }
39 > return rateLimiter
40 > }
41
42 // NewDefaultIncomingRateLimiter returns a default rate limiter
45 func NewDefaultIncomingRateLimiter(
46 rateFn RateFn,
47 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
48 > return NewDynamicRateLimiter(
49 > NewDefaultIncomingRateBurst(rateFn),
50 > defaultRefreshInterval,
51 > )
52 > }
53
54 // NewDefaultOutgoingRateLimiter returns a default rate limiter
57 func NewDefaultOutgoingRateLimiter(
58 rateFn RateFn,
59 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
60 > return NewDynamicRateLimiter(
61 > NewDefaultOutgoingRateBurst(rateFn),
62 > defaultRefreshInterval,
63 > )
64 > }
65
66 // NewDefaultRateLimiter returns a default rate limiter with a dynamic burst ratio
69 rateFn RateFn,
70 burstRatioFn BurstRatioFn,
71 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
72 > return NewDynamicRateLimiter(
73 > NewDefaultRateBurst(rateFn, burstRatioFn),
74 > defaultRefreshInterval,
75 > )
76 > }
77
78 // Allow immediately returns with true or false indicating if a rate limit
79 // token is available or not
80 > func (d *DynamicRateLimiterImpl) Allow() bool { dynamic_rate_limiter_impl.go
81 > d.maybeRefresh()
82 > return d.rateLimiter.Allow()
83 > }
84
85 // AllowN immediately returns with true or false indicating if n rate limit
86 // token is available or not
87 > func (d *DynamicRateLimiterImpl) AllowN(now time.Time, numToken int) bool { dynamic_rate_limiter_impl.go
88 > d.maybeRefresh()
89 > return d.rateLimiter.AllowN(now, numToken)
90 > }
91
92 // Reserve reserves a rate limit token
93 > func (d *DynamicRateLimiterImpl) Reserve() Reservation { dynamic_rate_limiter_impl.go
94 > d.maybeRefresh()
95 > return d.rateLimiter.Reserve()
96 > }
97
98 // ReserveN reserves n rate limit token
99 > func (d *DynamicRateLimiterImpl) ReserveN(now time.Time, numToken int) Reservation { dynamic_rate_limiter_impl.go
100 > d.maybeRefresh()
101 > return d.rateLimiter.ReserveN(now, numToken)
102 > }
103
104 // Wait waits up till deadline for a rate limit token
go.temporal.io/server/common/searchattribute/sadefs/constants.go 47 covered LOC · 16 ranges

Open complete file

261 }
262
263 > dbCustomSearchAttributeFieldNameRE = func() map[enumspb.IndexedValueType]*regexp.Regexp { constants.go
264 > res := map[enumspb.IndexedValueType]*regexp.Regexp{}
265 > for t := range defaultNumDBCustomSearchAttributes {
266 > res[t] = regexp.MustCompile(fmt.Sprintf(`^%s(0[1-9]|[1-9][0-9])$`, t.String()))
267 > }
268 > return res
269 }()
270 )
271
272 // System returns a clone of the system search attributes map.
273 > func System() map[string]enumspb.IndexedValueType { constants.go
274 > return maps.Clone(system)
275 > }
276
277 // Predefined returns a clone of the predefined search attributes map.
278 > func Predefined() map[string]enumspb.IndexedValueType { constants.go
279 > return maps.Clone(predefined)
280 > }
281
282 // PredefinedWhiteList returns a clone of the predefined whitelist search attributes map.
283 > func PredefinedWhiteList() map[string]enumspb.IndexedValueType { constants.go
284 > return maps.Clone(predefinedWhiteList)
285 > }
286
287 // Reserved returns a clone of the reserved field names map.
291
292 // IsSystem returns true if name is system search attribute
293 > func IsSystem(name string) bool { constants.go
294 > _, ok := system[name]
295 > return ok
296 > }
297
298 // IsReserved returns true if name is system reserved and can't be used as custom search attribute name.
299 > func IsReserved(name string) bool { constants.go
300 > if _, ok := system[name]; ok {
301 return true
302 }
303 > if _, ok := predefined[name]; ok { constants.go
304 return true
305 }
306 > if _, ok := reserved[name]; ok { constants.go
307 return true
308 }
309 > return strings.HasPrefix(name, ReservedPrefix) constants.go
310 }
311
323
324 // IsChasmSystem returns true if name is a system search attribute used by CHASM
325 > func IsChasmSystem(name string) bool { constants.go
326 > _, ok := chasmSystemSearchAttributes[name]
327 > return ok
328 > }
329
330 // IsChasmOverridableSystem returns true if name is a system search attribute whose dedicated
331 // visibility column a CHASM component may override with its own value. See
332 // chasmOverridableSystemSearchAttributes for the semantics and exclusions.
333 > func IsChasmOverridableSystem(name string) bool { constants.go
334 > _, ok := chasmOverridableSystemSearchAttributes[name]
335 > return ok
336 > }
337
338 // ChasmOverridableSystem returns a clone of the CHASM-overridable system search attributes set.
343 // GetSqlDbColName maps system and reserved search attributes to column names for SQL tables.
344 // If the input is not a system or reserved search attribute, then it returns the input.
345 > func GetSqlDbColName(name string) string { constants.go
346 > if fieldName, ok := sqlDbSystemNameToColName[name]; ok {
347 > return fieldName constants.go
348 > }
349 return name
350 }
352 func GetDBIndexSearchAttributes(
353 override map[enumspb.IndexedValueType]int,
354 > ) *persistencespb.IndexSearchAttributes { constants.go
355 > csa := map[string]enumspb.IndexedValueType{}
356 > for saType, defaultNumAttrs := range defaultNumDBCustomSearchAttributes {
357 > numAttrs := defaultNumAttrs
358 > if value, ok := override[saType]; ok {
359 numAttrs = value
360 }
361 > for i := range numAttrs { constants.go
362 > csa[fmt.Sprintf("%s%02d", saType.String(), i+1)] = saType
363 > }
364 }
365 > return &persistencespb.IndexSearchAttributes{ constants.go
366 > CustomSearchAttributes: csa,
367 > }
368 }
369
go.temporal.io/server/service/matching/handler.go 47 covered LOC · 3 ranges

Open complete file

90 func NewHandler(
91 params HandlerParams,
92 > ) *Handler { handler.go
93 > handler := &Handler{
94 > config: params.Config,
95 > metricsHandler: params.MetricsHandler,
96 > logger: params.Logger,
97 > throttledLogger: params.ThrottledLogger,
98 > engine: NewEngine(
99 > params.TaskManager,
100 > params.FairTaskManager,
101 > params.HistoryClient,
102 > params.MatchingRawClient, // Use non retry client inside matching
103 > params.WorkerDeploymentClient,
104 > params.Config,
105 > params.Logger,
106 > params.ThrottledLogger,
107 > params.MetricsHandler,
108 > params.NamespaceRegistry,
109 > params.HostInfoProvider,
110 > params.MatchingServiceResolver,
111 > params.ClusterMetadata,
112 > params.NamespaceReplicationQueue,
113 > params.VisibilityManager,
114 > params.NexusEndpointManager,
115 > params.TestHooks,
116 > params.SearchAttributeProvider,
117 > params.SearchAttributeMapperProvider,
118 > params.RateLimiter,
119 > params.Serializer,
120 > params.TaskHookFactories,
121 > params.PartitionScalerFactory,
122 > ),
123 > namespaceRegistry: params.NamespaceRegistry,
124 > workersRegistry: params.WorkersRegistry,
125 > }
126 >
127 > // prevent from serving requests before matching engine is started and ready
128 > handler.startWG.Add(1)
129 >
130 > return handler
131 > }
132
133 // Start starts the handler
134 > func (h *Handler) Start() { handler.go
135 > h.engine.Start()
136 > h.startWG.Done()
137 > }
138
139 // Stop stops the handler
140 > func (h *Handler) Stop() { handler.go
141 > h.engine.Stop()
142 > }
143
144 func (h *Handler) opMetricsHandler(
go.temporal.io/server/common/rpc/interceptor/redirection.go 46 covered LOC · 10 ranges

Open complete file

200 timeSource clock.TimeSource,
201 clusterMetadata cluster.Metadata,
202 > ) *Redirection { redirection.go
203 > dcRedirectionPolicy := RedirectionPolicyGenerator(
204 > clusterMetadata,
205 > enabledForNS,
206 > selectedAPIsOnlyForNS,
207 > namespaceCache,
208 > policy,
209 > )
210 >
211 > return &Redirection{
212 > currentClusterName: clusterMetadata.GetCurrentClusterName(),
213 > redirectionPolicy: dcRedirectionPolicy,
214 > namespaceCache: namespaceCache,
215 > logger: logger,
216 > clientBean: clientBean,
217 > metricsHandler: metricsHandler,
218 > timeSource: timeSource,
219 > }
220 > }
221
222 // WithRedirectResponses returns a copy of the interceptor that treats the given fullMethod ->
240 info *grpc.UnaryServerInfo,
241 handler grpc.UnaryHandler,
242 > ) (_ any, retError error) { redirection.go
243 > defer log.CapturePanic(i.logger, &retError)
244 > if raFn, ok := i.redirectResponsesByFullMethod[info.FullMethod]; ok {
245 if !i.RedirectionAllowed(ctx) {
246 return handler(ctx, req)
256 }
257
258 > if !strings.HasPrefix(info.FullMethod, api.WorkflowServicePrefix) { redirection.go
259 return handler(ctx, req)
260 }
261 > if !i.RedirectionAllowed(ctx) { redirection.go
262 return handler(ctx, req)
263 }
264
265 > methodName := api.MethodName(info.FullMethod) redirection.go
266 > if _, ok := localAPIResponses[methodName]; ok {
267 > return i.handleLocalAPIInvocation(ctx, req, handler, methodName)
268 > }
269 if raFn, ok := globalAPIResponses[methodName]; ok {
270 namespaceName, err := GetNamespaceName(i.namespaceCache, req)
286 handler grpc.UnaryHandler,
287 methodName string,
288 > ) (_ any, retError error) { redirection.go
289 > scope, startTime := i.BeforeCall(dcRedirectionMetricsPrefix + methodName)
290 > defer func() {
291 > i.AfterCall(scope, startTime, i.currentClusterName, "local", retError)
292 > }()
293 > return handler(ctx, req)
294 }
295
336 func (i *Redirection) BeforeCall(
337 operation string,
338 > ) (metrics.Handler, time.Time) { redirection.go
339 > return i.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.ServiceRoleTag(metrics.DCRedirectionRoleTagValue)), i.timeSource.Now()
340 > }
341
342 func (i *Redirection) AfterCall(
346 namespaceName string,
347 retError error,
348 > ) { redirection.go
349 > // Only emit redirection metrics when actual cross-cluster redirection occurred
350 > if targetClusterName != i.currentClusterName {
351 metricsHandler = metricsHandler.WithTags(metrics.TargetClusterTag(targetClusterName))
352 metrics.ClientRedirectionLatency.With(metricsHandler).Record(i.timeSource.Now().Sub(startTime))
362 func (i *Redirection) RedirectionAllowed(
363 ctx context.Context,
364 > ) bool { redirection.go
365 > // default to allow dc redirection
366 > values := metadata.ValueFromIncomingContext(ctx, DCRedirectionContextHeaderName)
367 > if len(values) == 0 {
368 > return true redirection.go
369 > }
370 allowed, err := strconv.ParseBool(values[0])
371 if err != nil {
go.temporal.io/server/service/frontend/nexus_operation_http_handler.go 46 covered LOC · 2 ranges

Open complete file

65 logger log.Logger,
66 httpTraceProvider commonnexus.HTTPClientTraceProvider,
67 > ) *NexusOperationHTTPHandler { nexus_operation_http_handler.go
68 > return &NexusOperationHTTPHandler{
69 > base: nexusrpc.BaseHTTPHandler{
70 > Logger: log.NewSlogLogger(logger),
71 > FailureConverter: nexusrpc.DefaultFailureConverter(),
72 > },
73 > logger: logger,
74 > enpointRegistry: endpointRegistry,
75 > namespaceRegistry: namespaceRegistry,
76 > auth: authInterceptor,
77 > namespaceValidationInterceptor: namespaceValidationInterceptor,
78 > namespaceRateLimitInterceptor: namespaceRateLimitInterceptor,
79 > namespaceConcurrencyLimitInterceptor: namespaceConcurrencyLimitInterceptor,
80 > rateLimitInterceptor: rateLimitInterceptor,
81 > preprocessErrorCounter: metricsHandler.Counter(metrics.NexusRequestPreProcessErrors.Name()).Record,
82 > nexusHandler: nexusrpc.NewHTTPHandler(nexusrpc.HandlerOptions{
83 > Handler: &nexusHandler{
84 > logger: logger,
85 > metricsHandler: metricsHandler,
86 > clusterMetadata: clusterMetadata,
87 > namespaceRegistry: namespaceRegistry,
88 > matchingClient: matchingservice.MatchingServiceClient(matchingClient),
89 > auth: authInterceptor,
90 > telemetryInterceptor: telemetryInterceptor,
91 > requestErrorHandler: requestErrorHandler,
92 > redirectionInterceptor: redirectionInterceptor,
93 > forwardingEnabledForNamespace: serviceConfig.EnableNamespaceNotActiveAutoForwarding,
94 > forwardingClients: clientCache,
95 > payloadSizeLimit: serviceConfig.BlobSizeLimitError,
96 > headersBlacklist: serviceConfig.NexusRequestHeadersBlacklist,
97 > useForwardByEndpoint: serviceConfig.NexusForwardRequestUseEndpoint,
98 > metricTagConfig: serviceConfig.NexusOperationsMetricTagConfig,
99 > httpTraceProvider: httpTraceProvider,
100 > },
101 > GetResultTimeout: serviceConfig.KeepAliveMaxConnectionIdle(),
102 > Logger: log.NewSlogLogger(logger),
103 > Serializer: commonnexus.PayloadSerializer,
104 > }),
105 > }
106 > }
107
108 > func (h *NexusOperationHTTPHandler) RegisterRoutes(r *mux.Router) { nexus_operation_http_handler.go
109 > r.PathPrefix("/" + commonnexus.RouteDispatchNexusTaskByNamespaceAndTaskQueue.Representation() + "/").
110 > HandlerFunc(h.dispatchNexusTaskByNamespaceAndTaskQueue)
111 > r.PathPrefix("/" + commonnexus.RouteDispatchNexusTaskByEndpoint.Representation() + "/").
112 > HandlerFunc(h.dispatchNexusTaskByEndpoint)
113 > }
114
115 func (h *NexusOperationHTTPHandler) writeFailure(writer http.ResponseWriter, r *http.Request, err error) {
go.temporal.io/server/service/history/queues/slice.go 46 covered LOC · 10 ranges

Open complete file

69 maxPendingKeysFn func() int,
70 metricsHandler metrics.Handler,
71 > ) *SliceImpl { slice.go
72 > s := &SliceImpl{
73 > paginationFnProvider: paginationFnProvider,
74 > executableFactory: executableFactory,
75 > scope: scope,
76 > iterators: []Iterator{
77 > NewIterator(paginationFnProvider, scope.Range),
78 > },
79 > executableTracker: newExecutableTracker(grouper),
80 > monitor: monitor,
81 > maxPredicateSizeFn: maxPredicateSizeFn,
82 > maxPendingKeysFn: maxPendingKeysFn,
83 > metricsHandler: metricsHandler,
84 > }
85 > s.ensurePredicateSizeLimit()
86 > return s
87 > }
88
89 > func (s *SliceImpl) Scope() Scope { slice.go
90 > s.stateSanityCheck()
91 > return s.scope
92 > }
93
94 func (s *SliceImpl) CanSplitByRange(key tasks.Key) bool {
360 }
361
362 > func (s *SliceImpl) SelectTasks(readerID int64, batchSize int) ([]Executable, error) { slice.go
363 > s.stateSanityCheck()
364 >
365 > if len(s.iterators) == 0 {
366 return []Executable{}, nil
367 }
368
369 > defer func() { slice.go
370 > s.monitor.SetSlicePendingTaskCount(s, len(s.pendingExecutables))
371 > }()
372
373 > executables := make([]Executable, 0, batchSize) slice.go
374 > for len(executables) < batchSize && len(s.iterators) != 0 {
375 > if s.iterators[0].HasNext() {
376 task, err := s.iterators[0].Next()
377 if err != nil {
398 s.add(executable)
399 executables = append(executables, executable)
400 > } else { slice.go
401 > s.iterators = s.iterators[1:]
402 > }
403 }
404
405 > return executables, nil slice.go
406 }
407
408 > func (s *SliceImpl) MoreTasks() bool { slice.go
409 > s.stateSanityCheck()
410 >
411 > return len(s.iterators) != 0
412 > }
413
414 func (s *SliceImpl) TaskStats() TaskStats {
440 }
441
442 > func (s *SliceImpl) stateSanityCheck() { slice.go
443 > if s.destroyed {
444 panic("Can not invoke method on destroyed queue slice")
445 }
468 }
469
470 > func (s *SliceImpl) ensurePredicateSizeLimit() { slice.go
471 > maxPredicateSize := s.maxPredicateSizeFn()
472 > // 0 == unlimited
473 > if maxPredicateSize > 0 && s.scope.Predicate.Size() > maxPredicateSize {
474 // Due to the limitations in predicate merging logic, the predicate size can easily grow unbounded.
475 // The simplest mitigation is to stop merging and replace with the univeral predicate.
go.temporal.io/server/service/matching/nexus_endpoint_client.go 46 covered LOC · 11 ranges

Open complete file

74 endpointsRefreshInterval dynamicconfig.DurationPropertyFn,
75 persistence p.NexusEndpointManager,
76 > ) *nexusEndpointClient { nexus_endpoint_client.go
77 > return &nexusEndpointClient{
78 > endpointsRefreshInterval: endpointsRefreshInterval,
79 > persistence: persistence,
80 > tableVersionChanged: make(chan struct{}),
81 > }
82 > }
83
84 func (m *nexusEndpointClient) CreateNexusEndpoint(
353 // notifyOwnershipChanged starts or stops a background routine which watches the Nexus endpoints table version for
354 // changes. This is only expected to be called from matchingEngineImpl.notifyNexusEndpointsOwnershipChange()
355 > func (m *nexusEndpointClient) notifyOwnershipChanged(isOwner bool) { nexus_endpoint_client.go
356 > var oldHandle *goro.Handle
357 >
358 > m.refreshLock.Lock()
359 > if isOwner && m.refreshHandle == nil {
360 > // Just acquired ownership. Start refresh loop on table version to catch any updates from previous owner. nexus_endpoint_client.go
361 > backgroundCtx := headers.SetCallerInfo(
362 > context.Background(),
363 > headers.SystemBackgroundHighCallerInfo,
364 > )
365 > m.refreshHandle = goro.NewHandle(backgroundCtx)
366 > m.refreshHandle.Go(m.refreshTableVersion)
367 > } else if !isOwner && m.refreshHandle != nil { nexus_endpoint_client.go
368 > // Just lost ownership. Stop table version refresh loop. nexus_endpoint_client.go
369 > oldHandle = m.refreshHandle
370 > m.refreshHandle = nil
371 > }
372 > m.refreshLock.Unlock() nexus_endpoint_client.go
373 >
374 > if oldHandle != nil {
375 > oldHandle.Cancel() nexus_endpoint_client.go
376 > <-oldHandle.Done()
377 > }
378 }
379
380 > func (m *nexusEndpointClient) refreshTableVersion(ctx context.Context) error { nexus_endpoint_client.go
381 > for ctx.Err() == nil {
382 > m.checkTableVersion(ctx) nexus_endpoint_client.go
383 > util.InterruptibleSleep(ctx, backoff.Jitter(m.endpointsRefreshInterval(), 0.2))
384 > }
385 > return ctx.Err() nexus_endpoint_client.go
386 }
387
388 > func (m *nexusEndpointClient) checkTableVersion(ctx context.Context) { nexus_endpoint_client.go
389 > // Acquire lock to make sure we are not in the middle of an update.
390 > m.Lock()
391 > defer m.Unlock()
392 >
393 > resp, err := m.persistence.ListNexusEndpoints(ctx, &p.ListNexusEndpointsRequest{
394 > LastKnownTableVersion: 0,
395 > PageSize: 0,
396 > })
397 > if err != nil || resp.TableVersion != m.tableVersion {
398 m.hasLoadedEndpoints.Store(false)
399 ch := m.tableVersionChanged
go.temporal.io/server/service/worker/scheduler/fx.go 46 covered LOC · 5 ranges

Open complete file

85 specBuilder *SpecBuilder,
86 params activityDeps,
87 > ) fxResult { fx.go
88 > return fxResult{
89 > Component: &workerComponent{
90 > specBuilder: specBuilder,
91 > activityDeps: params,
92 > enabledForNs: dynamicconfig.WorkerEnableScheduler.Get(dc),
93 > enableCHASMMigration: dynamicconfig.EnableCHASMSchedulerMigration.Get(dc),
94 > chasmMigrationRolloutPercent: dynamicconfig.CHASMSchedulerMigrationRolloutPercent.Get(dc),
95 > migrateWithRunningWorkflows: dynamicconfig.EnableCHASMSchedulerMigrationWithRunningWorkflows.Get(dc),
96 > globalNSStartWorkflowRPS: dynamicconfig.SchedulerNamespaceStartWorkflowRPS.Subscribe(dc),
97 > maxBlobSize: dynamicconfig.BlobSizeLimitError.Get(dc),
98 > localActivitySleepLimit: dynamicconfig.SchedulerLocalActivitySleepLimit.Get(dc),
99 > },
100 > }
101 > }
102
103 > func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
104 > return &workercommon.PerNSDedicatedWorkerOptions{
105 > Enabled: s.enabledForNs(ns.Name().String()),
106 > }
107 > }
108
109 > func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, details workercommon.RegistrationDetails) func() { fx.go
110 > nsName := ns.Name().String()
111 > wfFunc := func(ctx workflow.Context, args *schedulespb.StartScheduleArgs) error {
112 key := fmt.Appendf(nil, "%s\x00%s", nsName, args.State.ScheduleId)
113 enableMigration := func() bool {
120 return schedulerWorkflowWithSpecBuilder(ctx, args, s.specBuilder, enableMigration, migrateWithRunningWorkflows)
121 }
122 > registry.RegisterWorkflowWithOptions(wfFunc, workflow.RegisterOptions{Name: WorkflowType}) fx.go
123 >
124 > activities, cleanup := s.newActivities(ns.Name(), ns.ID(), details)
125 > registry.RegisterActivity(activities)
126 > return cleanup
127 }
128
129 > func (s *workerComponent) newActivities(name namespace.Name, id namespace.ID, details workercommon.RegistrationDetails) (*activities, func()) { fx.go
130 > const burstRatio = 1.0
131 >
132 > lim := quotas.NewRateLimiter(1, 1)
133 > cb := func(rps float64) {
134 > localRPS := rps * float64(details.Multiplicity) / float64(details.TotalWorkers)
135 > burst := max(1, int(math.Ceil(localRPS*burstRatio)))
136 > lim.SetRateBurst(localRPS, burst)
137 > }
138 > initialRPS, cancel := s.globalNSStartWorkflowRPS(name.String(), cb)
139 > cb(initialRPS)
140 >
141 > return &activities{
142 > activityDeps: s.activityDeps,
143 > namespace: name,
144 > namespaceID: id,
145 > startWorkflowRateLimiter: lim,
146 > maxBlobSize: func() int { return s.maxBlobSize(name.String()) },
147 localActivitySleepLimit: func() time.Duration { return s.localActivitySleepLimit(name.String()) },
148 }, cancel
go.temporal.io/server/api/historyservice/v1/request_response.pb.go 45 covered LOC · 1 range

Open complete file

11956 }
11957
11958 > func init() { file_temporal_server_api_historyservice_v1_request_response_proto_init() } request_response.pb.go
11959 > func file_temporal_server_api_historyservice_v1_request_response_proto_init() {
11960 > if File_temporal_server_api_historyservice_v1_request_response_proto != nil {
11961 > return
11962 > }
11963 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107].OneofWrappers = []any{
11964 > (*StreamWorkflowReplicationMessagesRequest_SyncReplicationState)(nil),
11965 > }
11966 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108].OneofWrappers = []any{
11967 > (*StreamWorkflowReplicationMessagesResponse_Messages)(nil),
11968 > }
11969 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134].OneofWrappers = []any{
11970 > (*CompleteNexusOperationChasmRequest_Success)(nil),
11971 > (*CompleteNexusOperationChasmRequest_Failure)(nil),
11972 > }
11973 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136].OneofWrappers = []any{
11974 > (*CompleteNexusOperationRequest_Success)(nil),
11975 > (*CompleteNexusOperationRequest_Failure)(nil),
11976 > }
11977 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[162].OneofWrappers = []any{
11978 > (*ExecuteMultiOperationRequest_Operation_StartWorkflow)(nil),
11979 > (*ExecuteMultiOperationRequest_Operation_UpdateWorkflow)(nil),
11980 > }
11981 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[163].OneofWrappers = []any{
11982 > (*ExecuteMultiOperationResponse_Response_StartWorkflow)(nil),
11983 > (*ExecuteMultiOperationResponse_Response_UpdateWorkflow)(nil),
11984 > }
11985 > type x struct{}
11986 > out := protoimpl.TypeBuilder{
11987 > File: protoimpl.DescBuilder{
11988 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
11989 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc)),
11990 > NumEnums: 0,
11991 > NumMessages: 171,
11992 > NumExtensions: 1,
11993 > NumServices: 0,
11994 > },
11995 > GoTypes: file_temporal_server_api_historyservice_v1_request_response_proto_goTypes,
11996 > DependencyIndexes: file_temporal_server_api_historyservice_v1_request_response_proto_depIdxs,
11997 > MessageInfos: file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes,
11998 > ExtensionInfos: file_temporal_server_api_historyservice_v1_request_response_proto_extTypes,
11999 > }.Build()
12000 > File_temporal_server_api_historyservice_v1_request_response_proto = out.File
12001 > file_temporal_server_api_historyservice_v1_request_response_proto_goTypes = nil
12002 > file_temporal_server_api_historyservice_v1_request_response_proto_depIdxs = nil
12003 }
go.temporal.io/server/common/future/future_impl.go 45 covered LOC · 11 ranges

Open complete file

29 )
30
31 > func NewFuture[T any]() *FutureImpl[T] { future_impl.go
32 > var value T
33 > return &FutureImpl[T]{
34 > status: pending,
35 > readyCh: make(chan struct{}),
36 >
37 > value: value,
38 > err: nil,
39 > }
40 > }
41
42 func (f *FutureImpl[T]) Get(
43 ctx context.Context,
44 > ) (T, error) { future_impl.go
45 > if f.Ready() {
46 > return f.value, f.err future_impl.go
47 > }
48
49 > select { future_impl.go
50 > case <-f.readyCh: future_impl.go
51 > return f.value, f.err
52 case <-ctx.Done():
53 var value T
67 value T,
68 err error,
69 > ) { future_impl.go
70 > // cannot directly set status to `ready`, to prevent data race in case multiple `Get` occurs
71 > // instead set status to `setting` to prevent concurrent completion of this future
72 > if !atomic.CompareAndSwapInt32(
73 > &f.status,
74 > pending,
75 > setting,
76 > ) {
77 panic("future has already been completed")
78 }
79
80 > f.value = value future_impl.go
81 > f.err = err
82 > atomic.CompareAndSwapInt32(&f.status, setting, ready)
83 > close(f.readyCh)
84 }
85
88 value T,
89 err error,
90 > ) bool { future_impl.go
91 > if !atomic.CompareAndSwapInt32(
92 > &f.status,
93 > pending,
94 > setting,
95 > ) {
96 > return false future_impl.go
97 > }
98
99 > f.value = value future_impl.go
100 > f.err = err
101 > atomic.CompareAndSwapInt32(&f.status, setting, ready)
102 > close(f.readyCh)
103 > return true
104 }
105
106 > func (f *FutureImpl[T]) Ready() bool { future_impl.go
107 > return atomic.LoadInt32(&f.status) == ready
108 > }
go.temporal.io/server/common/persistence/execution_manager.go 45 covered LOC · 12 ranges

Open complete file

48 transactionSizeLimit dynamicconfig.IntPropertyFn,
49 enableBestEffortDeleteTasksOnWorkflowUpdate dynamicconfig.BoolPropertyFn,
50 > ) ExecutionManager { execution_manager.go
51 > return &executionManagerImpl{
52 > serializer: serializer,
53 > eventBlobCache: eventBlobCache,
54 > persistence: persistence,
55 > logger: logger,
56 > pagingTokenSerializer: newJSONHistoryTokenSerializer(),
57 > transactionSizeLimit: transactionSizeLimit,
58 > enableBestEffortDeleteTasksOnWorkflowUpdate: enableBestEffortDeleteTasksOnWorkflowUpdate,
59 > }
60 > }
61
62 > func (m *executionManagerImpl) GetName() string { execution_manager.go
63 > return m.persistence.GetName()
64 > }
65
66 func (m *executionManagerImpl) GetHistoryBranchUtil() HistoryBranchUtil {
960 ctx context.Context,
961 request *GetHistoryTasksRequest,
962 > ) (*GetHistoryTasksResponse, error) { execution_manager.go
963 > if err := validateTaskRange(
964 > request.TaskCategory.Type(),
965 > request.InclusiveMinTaskKey,
966 > request.ExclusiveMaxTaskKey,
967 > ); err != nil {
968 return nil, err
969 }
970
971 > resp, err := m.persistence.GetHistoryTasks(ctx, request) execution_manager.go
972 > if err != nil {
973 return nil, err
974 }
975
976 > historyTasks := make([]tasks.Task, 0, len(resp.Tasks)) execution_manager.go
977 > for _, internalTask := range resp.Tasks {
978 task, err := m.serializer.DeserializeTask(request.TaskCategory, internalTask.Blob)
979 if err != nil {
989 }
990
991 > return &GetHistoryTasksResponse{ execution_manager.go
992 > Tasks: historyTasks,
993 > NextPageToken: resp.NextPageToken,
994 > }, nil
995 }
996
1077 }
1078
1079 > func (m *executionManagerImpl) Close() { execution_manager.go
1080 > m.persistence.Close()
1081 > }
1082
1083 func (m *executionManagerImpl) trimHistoryNode(
1328 minTaskKey tasks.Key,
1329 maxTaskKey tasks.Key,
1330 > ) error { execution_manager.go
1331 > minTaskIDSpecified := minTaskKey.TaskID != 0
1332 > minFireTimeSpecified := !minTaskKey.FireTime.IsZero() && !minTaskKey.FireTime.Equal(tasks.DefaultFireTime)
1333 > maxTaskIDSpecified := maxTaskKey.TaskID != 0
1334 > maxFireTimeSpecified := !maxTaskKey.FireTime.IsZero() && !maxTaskKey.FireTime.Equal(tasks.DefaultFireTime)
1335 >
1336 > switch taskCategoryType {
1337 > case tasks.CategoryTypeImmediate:
1338 > if !maxTaskIDSpecified {
1339 return serviceerror.NewInvalidArgument("invalid task range, max taskID must be specified for immediate task category")
1340 }
1341 > if minFireTimeSpecified || maxFireTimeSpecified { execution_manager.go
1342 return serviceerror.NewInvalidArgument("invalid task range, fireTime must be empty for immediate task category")
1343 }
1344 > case tasks.CategoryTypeScheduled: execution_manager.go
1345 > if !maxFireTimeSpecified {
1346 return serviceerror.NewInvalidArgument("invalid task range, max fire time must be specified for scheduled task category")
1347 }
1348 > if minTaskIDSpecified || maxTaskIDSpecified { execution_manager.go
1349 return serviceerror.NewInvalidArgument("invalid task range, taskID must be empty for scheduled task category")
1350 }
go.temporal.io/server/common/persistence/serialization/serializer.go 45 covered LOC · 21 ranges

Open complete file

139 )
140
141 > func NewSerializer() Serializer { serializer.go
142 > return &serializerImpl{encodingType: encodingTypeFromEnv()}
143 > }
144
145 func (t *serializerImpl) EncodingType() enumspb.EncodingType {
265 }
266
267 > func (t *serializerImpl) SerializeClusterMetadata(cm *persistencespb.ClusterMetadata) (*commonpb.DataBlob, error) { serializer.go
268 > if cm == nil {
269 cm = &persistencespb.ClusterMetadata{}
270 }
271 > return t.serialize(cm) serializer.go
272 }
273
274 > func (t *serializerImpl) DeserializeClusterMetadata(data *commonpb.DataBlob) (*persistencespb.ClusterMetadata, error) { serializer.go
275 > if data == nil {
276 return nil, nil
277 }
278 > if len(data.Data) == 0 { serializer.go
279 return nil, nil
280 }
281
282 > cm := &persistencespb.ClusterMetadata{} serializer.go
283 > err := Decode(data, cm)
284 > if err != nil {
285 return nil, err
286 }
287 > return cm, nil serializer.go
288 }
289
290 > func (t *serializerImpl) serialize(p proto.Message) (*commonpb.DataBlob, error) { serializer.go
291 > if p == nil {
292 return nil, nil
293 }
294 > blob, err := encodeBlob(p, t.encodingType) serializer.go
295 > if err != nil {
296 return nil, NewSerializationError(t.encodingType, err)
297 }
298 > return blob, nil serializer.go
299 }
300
372 func (e *DeserializationError) IsTerminalTaskError() bool { return true }
373
374 > func (t *serializerImpl) ShardInfoToBlob(info *persistencespb.ShardInfo) (*commonpb.DataBlob, error) { serializer.go
375 > return encodeBlob(info, t.encodingType)
376 > }
377
378 > func (t *serializerImpl) ShardInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ShardInfo, error) { serializer.go
379 > shardInfo := &persistencespb.ShardInfo{}
380 > err := Decode(data, shardInfo)
381 >
382 > if err != nil {
383 return nil, err
384 }
385
386 > if shardInfo.GetReplicationDlqAckLevel() == nil { serializer.go
387 > shardInfo.ReplicationDlqAckLevel = make(map[string]int64) serializer.go
388 > }
389
390 > if shardInfo.GetQueueStates() == nil { serializer.go
391 > shardInfo.QueueStates = make(map[int32]*persistencespb.QueueState) serializer.go
392 > }
393 > for _, queueState := range shardInfo.QueueStates { serializer.go
394 if queueState.ReaderStates == nil {
395 queueState.ReaderStates = make(map[int64]*persistencespb.QueueReaderState)
402 }
403
404 > return shardInfo, nil serializer.go
405 }
406
407 > func (t *serializerImpl) NamespaceDetailToBlob(info *persistencespb.NamespaceDetail) (*commonpb.DataBlob, error) { serializer.go
408 > return encodeBlob(info, t.encodingType)
409 > }
410
411 > func (t *serializerImpl) NamespaceDetailFromBlob(data *commonpb.DataBlob) (*persistencespb.NamespaceDetail, error) { serializer.go
412 > result := &persistencespb.NamespaceDetail{}
413 > return result, Decode(data, result)
414 > }
415
416 func (t *serializerImpl) HistoryTreeInfoToBlob(info *persistencespb.HistoryTreeInfo) (*commonpb.DataBlob, error) {
562 }
563
564 > func (t *serializerImpl) QueueMetadataToBlob(metadata *persistencespb.QueueMetadata) (*commonpb.DataBlob, error) { serializer.go
565 > // TODO change ENCODING_TYPE_JSON to ENCODING_TYPE_PROTO3
566 > return encodeBlob(metadata, enumspb.ENCODING_TYPE_JSON)
567 > }
568
569 func (t *serializerImpl) QueueMetadataFromBlob(data *commonpb.DataBlob) (*persistencespb.QueueMetadata, error) {
go.temporal.io/server/common/quotas/map_request_rate_limiter_impl.go 45 covered LOC · 10 ranges

Open complete file

40 rateLimiterGenFn RequestRateLimiterFn,
41 rateLimiterKeyFn RequestRateLimiterKeyFn[K],
42 > ) *MapRequestRateLimiterImpl[K] { map_request_rate_limiter_impl.go
43 > return &MapRequestRateLimiterImpl[K]{
44 > rateLimiterGenFn: rateLimiterGenFn,
45 > rateLimiterKeyFn: rateLimiterKeyFn,
46 > rateLimiters: make(map[K]*rateLimiterEntry),
47 > ttlNano: int64(rateLimiterTTL),
48 > cleanupTicker: time.NewTicker(rateLimiterCleanupInterval),
49 > }
50 > }
51
52 > func namespaceRequestRateLimiterKeyFn(req Request) string { map_request_rate_limiter_impl.go
53 > return req.Caller
54 > }
55
56 func NewNamespaceRequestRateLimiter(
57 rateLimiterGenFn RequestRateLimiterFn,
58 > ) *MapRequestRateLimiterImpl[string] { map_request_rate_limiter_impl.go
59 > return NewMapRequestRateLimiter(rateLimiterGenFn, namespaceRequestRateLimiterKeyFn)
60 > }
61
62 // Allow attempts to allow a request to go through. The method returns
66 now time.Time,
67 request Request,
69 > rateLimiter := r.getOrInitRateLimiter(now, request)
70 > return rateLimiter.Allow(now, request)
71 > }
72
73 // Reserve returns a Reservation that indicates how long the caller
94 now time.Time,
95 req Request,
96 > ) RequestRateLimiter { map_request_rate_limiter_impl.go
97 > r.maybeCleanup(now)
98 >
99 > key := r.rateLimiterKeyFn(req)
100 > nowNano := now.UnixNano()
101 >
102 > r.RLock()
103 > entry, ok := r.rateLimiters[key]
104 > r.RUnlock()
105 >
106 > if ok {
107 > entry.lastAccess.Store(nowNano) map_request_rate_limiter_impl.go
108 > return entry.rateLimiter
109 > }
110
111 > newRateLimiter := r.rateLimiterGenFn(req) map_request_rate_limiter_impl.go
112 > r.Lock()
113 > defer r.Unlock()
114 >
115 > if entry, ok := r.rateLimiters[key]; ok {
116 entry.lastAccess.Store(nowNano)
117 return entry.rateLimiter
118 }
119
120 > entry = &rateLimiterEntry{rateLimiter: newRateLimiter} map_request_rate_limiter_impl.go
121 > entry.lastAccess.Store(nowNano)
122 > r.rateLimiters[key] = entry
123 > return newRateLimiter
124 }
125
127 // receive drains at most one ticker tick, so only one sweeper starts even if many
128 // callers reach here at once.
129 > func (r *MapRequestRateLimiterImpl[K]) maybeCleanup(now time.Time) { map_request_rate_limiter_impl.go
130 > select {
131 case <-r.cleanupTicker.C:
132 go r.cleanup(now)
134 }
135 }
go.temporal.io/server/common/quotas/rate_burst.go 44 covered LOC · 16 ranges

Open complete file

85 rateFn RateFn,
86 burstFn BurstFn,
87 > ) *RateBurstImpl { rate_burst.go
88 > return &RateBurstImpl{
89 > rateFn: rateFn,
90 > burstFn: burstFn,
91 > }
92 > }
93
94 func NewDefaultIncomingRateBurst(
95 rateFn RateFn,
96 > ) *RateBurstImpl { rate_burst.go
97 > return NewDefaultRateBurst(rateFn, func() float64 {
98 > return defaultIncomingRateBurstRatio rate_burst.go
99 > })
100 }
101
102 func NewDefaultOutgoingRateBurst(
103 rateFn RateFn,
104 > ) *RateBurstImpl { rate_burst.go
105 > return NewDefaultRateBurst(rateFn, func() float64 {
106 > return defaultOutgoingRateBurstRatio
107 > })
108 }
109
111 rateFn RateFn,
112 rateToBurstRatio BurstRatioFn,
113 > ) *RateBurstImpl { rate_burst.go
114 > burstFn := func() int {
115 > rate := rateFn() rate_burst.go
116 > if rate < 0 {
117 rate = 0
118 }
119
120 > ratio := rateToBurstRatio() rate_burst.go
121 > if ratio < 0 {
122 ratio = 0
123 }
124 > burst := int(rate * ratio) rate_burst.go
125 > if burst == 0 && rate > 0 && ratio > 0 {
126 > burst = 1 rate_burst.go
127 > }
128 > return burst rate_burst.go
129 }
130 > return NewRateBurst(rateFn, burstFn) rate_burst.go
131 }
132
133 > func (d *RateBurstImpl) Rate() float64 { rate_burst.go
134 > return d.rateFn()
135 > }
136
137 > func (d *RateBurstImpl) Burst() int { rate_burst.go
138 > return d.burstFn()
139 > }
140
141 func NewMutableRateBurst(
191 baseRateBurstFn RateBurst,
192 operatorRateRatio func() float64,
193 > ) *OperatorRateBurstImpl { rate_burst.go
194 > return &OperatorRateBurstImpl{
195 > operatorRateRatio: operatorRateRatio,
196 > baseRateBurstFn: baseRateBurstFn,
197 > }
198 > }
199
200 > func (c *OperatorRateBurstImpl) Rate() float64 { rate_burst.go
201 > return c.operatorRateRatio() * c.baseRateBurstFn.Rate()
202 > }
203
204 > func (c *OperatorRateBurstImpl) Burst() int { rate_burst.go
205 > return c.baseRateBurstFn.Burst()
206 > }
go.temporal.io/server/api/matchingservice/v1/request_response.pb.go 43 covered LOC · 1 range

Open complete file

6833 }
6834
6835 > func init() { file_temporal_server_api_matchingservice_v1_request_response_proto_init() } request_response.pb.go
6836 > func file_temporal_server_api_matchingservice_v1_request_response_proto_init() {
6837 > if File_temporal_server_api_matchingservice_v1_request_response_proto != nil {
6838 > return
6839 > }
6840 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[27].OneofWrappers = []any{
6841 > (*UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest_)(nil),
6842 > (*UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds_)(nil),
6843 > (*UpdateWorkerBuildIdCompatibilityRequest_PersistUnknownBuildId)(nil),
6844 > }
6845 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[29].OneofWrappers = []any{
6846 > (*GetWorkerVersioningRulesRequest_Request)(nil),
6847 > }
6848 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[31].OneofWrappers = []any{
6849 > (*UpdateWorkerVersioningRulesRequest_Request)(nil),
6850 > }
6851 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[37].OneofWrappers = []any{
6852 > (*SyncDeploymentUserDataRequest_UpdateVersionData)(nil),
6853 > (*SyncDeploymentUserDataRequest_ForgetVersion)(nil),
6854 > }
6855 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[56].OneofWrappers = []any{
6856 > (*DispatchNexusTaskResponse_HandlerError)(nil),
6857 > (*DispatchNexusTaskResponse_Response)(nil),
6858 > (*DispatchNexusTaskResponse_RequestTimeout)(nil),
6859 > (*DispatchNexusTaskResponse_Failure)(nil),
6860 > }
6861 > type x struct{}
6862 > out := protoimpl.TypeBuilder{
6863 > File: protoimpl.DescBuilder{
6864 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
6865 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc)),
6866 > NumEnums: 0,
6867 > NumMessages: 97,
6868 > NumExtensions: 0,
6869 > NumServices: 0,
6870 > },
6871 > GoTypes: file_temporal_server_api_matchingservice_v1_request_response_proto_goTypes,
6872 > DependencyIndexes: file_temporal_server_api_matchingservice_v1_request_response_proto_depIdxs,
6873 > MessageInfos: file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes,
6874 > }.Build()
6875 > File_temporal_server_api_matchingservice_v1_request_response_proto = out.File
6876 > file_temporal_server_api_matchingservice_v1_request_response_proto_goTypes = nil
6877 > file_temporal_server_api_matchingservice_v1_request_response_proto_depIdxs = nil
6878 }
go.temporal.io/server/common/metrics/tags.go 43 covered LOC · 21 ranges

Open complete file

101 // dual emit the metric with the all tag. If a blank namespace is provided then
102 // this converts that to an unknown namespace.
103 > func NamespaceTag(value string) Tag { tags.go
104 > if len(value) == 0 {
105 > value = unknownValue tags.go
106 > }
107 > return Tag{Key: namespace, Value: value} tags.go
108 }
109
119
120 // NamespaceUnknownTag returns a new namespace:unknown tag-value
121 > func NamespaceUnknownTag() Tag { tags.go
122 > return namespaceUnknownTag
123 > }
124
125 // NamespaceStateTag returns a new namespace state tag.
213
214 // WorkflowTypeTag returns a new workflow type tag.
215 > func WorkflowTypeTag(value string) Tag { tags.go
216 > if len(value) == 0 {
217 value = unknownValue
218 }
219 > return Tag{Key: workflowType, Value: value} tags.go
220 }
221
242
243 // Returns a new service role tag.
244 > func ServiceRoleTag(value string) Tag { tags.go
245 > if len(value) == 0 {
246 value = unknownValue
247 }
248 > return Tag{Key: ServiceRoleTagName, Value: value} tags.go
249 }
250
279 }
280
281 > func TaskTypeTag(value string) Tag { tags.go
282 > if len(value) == 0 {
283 > value = unknownValue tags.go
284 > }
285 > return Tag{Key: TaskTypeTagName, Value: value} tags.go
286 }
287
380 }
381
382 > func VisibilityPluginNameTag(value string) Tag { tags.go
383 > if value == "" {
384 value = unknownValue
385 }
386 > return Tag{Key: visibilityPluginNameTagName, Value: value} tags.go
387 }
388
389 > func VisibilityIndexNameTag(value string) Tag { tags.go
390 > if value == "" {
391 value = unknownValue
392 }
393 > return Tag{Key: visibilityIndexNameTagName, Value: value} tags.go
394 }
395
407 }
408
409 > func ServiceErrorTypeTag(err error) Tag { tags.go
410 > return Tag{Key: ErrorTypeTagName, Value: strings.TrimPrefix(util.ErrorType(err), errorPrefix)}
411 > }
412
413 func OutcomeTag(outcome string) Tag {
447 }
448
449 > func ServiceNameTag(value primitives.ServiceName) Tag { tags.go
450 > return Tag{Key: serviceName, Value: string(value)}
451 > }
452
453 func ActionType(value string) Tag {
455 }
456
457 > func OperationTag(value string) Tag { tags.go
458 > return Tag{Key: OperationTagName, Value: value}
459 > }
460
461 > func StringTag(key string, value string) Tag { tags.go
462 > return Tag{Key: key, Value: value}
463 > }
464
465 > func CacheTypeTag(value string) Tag { tags.go
466 > return Tag{Key: CacheTypeTagName, Value: value}
467 > }
468
469 > func PriorityTag(value locks.Priority) Tag { tags.go
470 > return Tag{Key: PriorityTagName, Value: strconv.Itoa(int(value))}
471 > }
472
473 // ReasonString is just a string but the special type is defined here to remind callers of ReasonTag to limit the
go.temporal.io/server/common/routing/route.go 43 covered LOC · 13 ranges

Open complete file

36
37 // NewRoute returns a new [Route] instance with the given components.
38 > func NewRoute[T any](components ...Component[T]) Route[T] { route.go
39 > return Route[T]{components: components}
40 > }
41
42 // RouteBuilder is a builder for the [Route] interface.
46
47 // NewBuilder creates a new [RouteBuilder] instance, which can be used to define a new [Route] via a fluent API.
48 > func NewBuilder[T any]() *RouteBuilder[T] { route.go
49 > return &RouteBuilder[T]{}
50 > }
51
52 // With adds a series of [Component] instances to the [Route].
53 > func (r *RouteBuilder[T]) With(c ...Component[T]) *RouteBuilder[T] { route.go
54 > r.components = append(r.components, c...)
55 > return r
56 > }
57
58 // Constant adds a [Constant] component to the [Route].
59 > func (r *RouteBuilder[T]) Constant(values ...string) *RouteBuilder[T] { route.go
60 > return r.With(Constant[T](values...))
61 > }
62
63 // StringVariable adds a [StringVariable] component to the [Route].
64 > func (r *RouteBuilder[T]) StringVariable(name string, getter func(*T) *string) *RouteBuilder[T] { route.go
65 > return r.With(StringVariable[T](name, getter))
66 > }
67
68 // Build returns a read-only [Route].
69 > func (r *RouteBuilder[T]) Build() Route[T] { route.go
70 > return NewRoute[T](r.components...)
71 > }
72
73 // Representation returns the [github.com/gorilla/mux] compatible string representation of the route for usage in a
75 // they're present in the components. We do this because it's easier to add a slash depending on the context than to
76 // remove it.
77 > func (r Route[T]) Representation() string { route.go
78 > return r.serialize(func(c Component[T]) string {
79 > return c.Representation()
80 > })
81 }
82
89 }
90
91 > func (r Route[T]) serialize(f func(c Component[T]) string) string { route.go
92 > var sb strings.Builder
93 > for i, c := range r.components {
94 > if i > 0 {
95 > sb.WriteString("/")
96 > }
97 > sb.WriteString(f(c))
98 }
99 > return sb.String() route.go
100 }
101
111 // Constant returns a [Component] that represents a series of constant HTTP path components in a Route.
112 // They will be joined via strings when used to construct a path or path representation.
113 > func Constant[T any](values ...string) constant[T] { route.go
114 > return values
115 > }
116
117 type constant[T any] []string
118
119 > func (s constant[T]) Representation() string { route.go
120 > return strings.Join(s, "/")
121 > }
122
123 func (s constant[T]) Serialize(T) string {
128
129 // StringVariable returns a [Component] that represents a string variable in a Route.
130 > func StringVariable[T any](name string, getter func(*T) *string) stringVariable[T] { route.go
131 > return stringVariable[T]{name, getter}
132 > }
133
134 type stringVariable[T any] struct {
137 }
138
139 > func (s stringVariable[T]) Representation() string { route.go
140 > return "{" + s.name + "}"
141 > }
142
143 func (s stringVariable[T]) Serialize(t T) string {
go.temporal.io/server/chasm/fields_iterator.go 42 covered LOC · 22 ranges

Open complete file

102
103 // unmanagedFieldsOf yields all non-CHASM managed fields of a struct.
104 > func unmanagedFieldsOf(valueT reflect.Type) iter.Seq[fieldInfo] { fields_iterator.go
105 > return func(yield func(fi fieldInfo) bool) {
106 > if valueT.Kind() == reflect.Pointer {
107 > valueT = valueT.Elem() fields_iterator.go
108 > }
109 > for field := range valueT.Fields() { fields_iterator.go
110 > fieldT := field.Type
111 > if fieldT == UnimplementedComponentT {
112 > continue fields_iterator.go
113 }
114
115 // Skip the data field, which is always CHASM-managed.
116 > if fieldT.AssignableTo(protoMessageT) { fields_iterator.go
117 > continue fields_iterator.go
118 }
119
120 > fieldN := fieldName(field) fields_iterator.go
121 > prefix := genericTypePrefix(fieldT)
122 > switch prefix {
123 case chasmFieldTypePrefix,
124 chasmMapTypePrefix,
125 chasmMSPointerType,
126 > chasmParentPointerTypePrefix: fields_iterator.go
127 > continue // Skip CHASM fields.
128 > default: fields_iterator.go
129 > if !yield(fieldInfo{typ: fieldT, name: fieldN}) {
130 return
131 }
135 }
136
137 > func genericTypePrefix(t reflect.Type) string { fields_iterator.go
138 > tn := t.String()
139 > if tn == chasmMSPointerType {
140 > return chasmMSPointerType fields_iterator.go
141 > }
142 > bracketPos := strings.Index(tn, "[") fields_iterator.go
143 > if bracketPos == -1 {
144 > return "" fields_iterator.go
145 > }
146 > return tn[:bracketPos+1] fields_iterator.go
147 }
148
149 > func fieldName(f reflect.StructField) string { fields_iterator.go
150 > if tagName := f.Tag.Get(fieldNameTag); tagName != "" {
151 return tagName
152 }
153 > return f.Name fields_iterator.go
154 }
155
161 // This is used at registration time to validate that archetypes using Visibility
162 // have configured a businessID alias.
163 > func hasVisibilityField(componentT reflect.Type) bool { fields_iterator.go
164 > if componentT.Kind() == reflect.Pointer {
165 > componentT = componentT.Elem() fields_iterator.go
166 > }
167 > if componentT.Kind() != reflect.Struct { fields_iterator.go
168 return false
169 }
170 > for field := range componentT.Fields() { fields_iterator.go
171 > fieldT := field.Type
172 > if fieldT == visibilityFieldT {
173 > return true fields_iterator.go
174 > }
175 }
176 > return false fields_iterator.go
177 }
go.temporal.io/server/service/history/queues/memory_scheduled_queue.go 42 covered LOC · 10 ranges

Open complete file

42 logger log.Logger,
43 metricsHandler metrics.Handler,
44 > ) *memoryScheduledQueue { memory_scheduled_queue.go
45 >
46 > nextTaskTimer := time.NewTimer(0)
47 > if !nextTaskTimer.Stop() {
48 <-nextTaskTimer.C
49 }
50
51 > return &memoryScheduledQueue{ memory_scheduled_queue.go
52 > taskQueue: collection.NewPriorityQueue[Executable](executableVisibilityTimeCompareLess),
53 > nextTaskTimer: nextTaskTimer,
54 > newTaskCh: make(chan Executable),
55 >
56 > timeSource: timeSource,
57 > logger: logger,
58 > metricsHandler: metricsHandler,
59 >
60 > status: common.DaemonStatusInitialized,
61 > shutdownCh: make(chan struct{}),
62 >
63 > scheduler: scheduler,
64 > }
65 }
66
72 }
73
74 > func (q *memoryScheduledQueue) Start() { memory_scheduled_queue.go
75 > if !atomic.CompareAndSwapInt32(&q.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
76 return
77 }
78
79 > q.logger.Info("", tag.LifeCycleStarting) memory_scheduled_queue.go
80 > defer q.logger.Info("", tag.LifeCycleStarted)
81 >
82 > q.shutdownWG.Add(1)
83 > go q.processQueueLoop()
84 }
85
86 > func (q *memoryScheduledQueue) Stop() { memory_scheduled_queue.go
87 > if !atomic.CompareAndSwapInt32(&q.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
88 return
89 }
90
91 > q.logger.Info("", tag.LifeCycleStopping) memory_scheduled_queue.go
92 > defer q.logger.Info("", tag.LifeCycleStopped)
93 >
94 > close(q.shutdownCh)
95 >
96 > if success := common.AwaitWaitGroup(&q.shutdownWG, time.Minute); !success {
97 q.logger.Warn("", tag.LifeCycleStopTimedout)
98 }
go.temporal.io/server/service/matching/workers/registry_impl.go 42 covered LOC · 7 ranges

Open complete file

80 )
81
82 > func newBucket() *bucket { registry_impl.go
83 > return &bucket{
84 > namespaces: make(map[namespace.ID]*nsEntries),
85 > order: list.New(),
86 > }
87 > }
88
89 // upsertHeartbeats inserts or refreshes a WorkerHeartbeat under the given namespace.
229
230 // NewRegistry creates a workers heartbeat registry with the given parameters.
231 > func NewRegistry(lc fx.Lifecycle, params RegistryParams) Registry { registry_impl.go
232 > m := newRegistryImpl(params)
233 > lc.Append(fx.StartStopHook(m.Start, m.Stop))
234 > return m
235 > }
236
237 > func newRegistryImpl(params RegistryParams) *registryImpl { registry_impl.go
238 > m := &registryImpl{
239 > buckets: make([]*bucket, params.NumBuckets()),
240 > maxItemsFn: params.MaxItems,
241 > ttlFn: params.TTL,
242 > minEvictAgeFn: params.MinEvictAge,
243 > evictionIntervalFn: params.EvictionInterval,
244 > seed: maphash.MakeSeed(),
245 > quit: make(chan struct{}),
246 > metricsHandler: params.MetricsHandler,
247 > metricsEmitter: &workerMetricsEmitter{
248 > handler: params.MetricsHandler,
249 > config: params.MetricsConfig,
250 > },
251 > }
252 >
253 > for i := range m.buckets {
254 > m.buckets[i] = newBucket()
255 > }
256 > return m
257 }
258
337
338 // evictLoop periodically triggers TTL and capacity-based eviction.
339 > func (m *registryImpl) evictLoop() { registry_impl.go
340 > for {
341 > select {
342 case <-time.After(m.evictionIntervalFn()):
343 m.evictByTTL()
345 m.recordUtilizationMetric()
346 m.recordWorkerCountMetric()
347 > case <-m.quit: registry_impl.go
348 > return
349 }
350 }
397
398 // Start begins the background eviction process.
399 > func (m *registryImpl) Start() { registry_impl.go
400 > go m.evictLoop()
401 > }
402
403 // Stop halts background eviction.
404 > func (m *registryImpl) Stop() { registry_impl.go
405 > close(m.quit)
406 > }
407
408 func (m *registryImpl) RecordWorkerHeartbeats(nsID namespace.ID, nsName namespace.Name, principal *commonpb.Principal, workerHeartbeat []*workerpb.WorkerHeartbeat) {
go.temporal.io/server/client/history/connections.go 41 covered LOC · 10 ranges

Open complete file

56 logger log.Logger,
57 connectionCloseDelay dynamicconfig.DurationPropertyFn,
58 > ) *connectionPoolImpl[C] { connections.go
59 > conns := &sync.Map{}
60 >
61 > c := &connectionPoolImpl[C]{
62 > conns: conns,
63 > historyServiceResolver: historyServiceResolver,
64 > rpcFactory: rpcFactory,
65 > clientCtor: clientCtor,
66 > logger: logger,
67 > connectionCloseDelay: connectionCloseDelay,
68 > }
69 >
70 > // Close cached conns whose host leaves the membership ring.
71 > c.watcher = goro.NewHandle(context.Background()).Go(c.watchMembership)
72 > return c
73 > }
74
75 // Close stops the watcher and closes all pooled connections.
76 > func (c *connectionPoolImpl[C]) Close() { connections.go
77 > if !c.closed.CompareAndSwap(false, true) {
78 return
79 }
80 > c.watcher.Cancel() connections.go
81 > <-c.watcher.Done()
82 > // Set closed before reaping so a concurrent create can't re-cache a conn.
83 > c.conns.Range(func(key, value any) bool {
84 c.conns.Delete(key)
85 if err := value.(clientConnection[C]).grpcConn.Close(); err != nil {
90 }
91
92 > func (c *connectionPoolImpl[C]) watchMembership(ctx context.Context) error { connections.go
93 > listenerName := fmt.Sprintf("%p", c.conns)
94 > ch := make(chan *membership.ChangedEvent, 1)
95 > if err := c.historyServiceResolver.AddListener(listenerName, ch); err != nil {
96 c.logger.Error("Failed to subscribe history connection pool to membership", tag.Error(err))
97 return err
98 }
99 > defer func() { _ = c.historyServiceResolver.RemoveListener(listenerName) }() connections.go
100
101 // Reap departed hosts via a per-address deadline checked by a single ticker;
102 // a re-add resets it to the latest removal.
103 > evictAt := make(map[rpcAddress]time.Time) connections.go
104 > ticker := time.NewTicker(evictionCheckInterval)
105 > defer ticker.Stop()
106 > for {
107 > select {
108 > case <-ctx.Done(): connections.go
109 > return nil
110 > case event := <-ch: connections.go
111 > for _, h := range event.HostsRemoved {
112 > evictAt[rpcAddress(h.GetAddress())] = time.Now().Add(c.connectionCloseDelay()) connections.go
113 > }
114 > for _, h := range event.HostsAdded { connections.go
115 > delete(evictAt, rpcAddress(h.GetAddress()))
116 > }
117 case <-ticker.C:
118 c.reapClosableConns(evictAt)
go.temporal.io/server/common/locks/priority_semaphore_impl.go 41 covered LOC · 11 ranges

Open complete file

67 // maximum combined weight for concurrent access, capable of handling multiple priority levels.
68 // Most of the logic is taken directly from golang's semaphore.Weighted.
69 > func NewPrioritySemaphore(n int) *PrioritySemaphoreImpl { priority_semaphore_impl.go
70 > waitLists := make([]*list.List, NumPriorities)
71 > for i := range waitLists {
72 > waitLists[i] = list.New()
73 > }
74 > return &PrioritySemaphoreImpl{
75 > size: n,
76 > waitLists: waitLists,
77 > }
78 }
79
81 // are available or ctx is done. On success, returns nil. On failure, returns
82 // ctx.Err() and leaves the semaphore unchanged.
83 > func (s *PrioritySemaphoreImpl) Acquire(ctx context.Context, priority Priority, n int) error { priority_semaphore_impl.go
84 > if priority >= NumPriorities {
85 // nolint:forbidigo
86 panic(fmt.Sprintf("semaphore: invalid priority %v, priority must be less than %v", priority, NumPriorities))
87 }
88
89 > done := ctx.Done() priority_semaphore_impl.go
90 >
91 > s.mu.Lock()
92 > select {
93 case <-done:
94 // ctx becoming done has "happened before" acquiring the semaphore,
98 s.mu.Unlock()
99 return ctx.Err()
101 }
102 // Check if acquisition can proceed without waiting
103 > if s.size-s.cur >= n && s.noWaiters(priority) { priority_semaphore_impl.go
104 > // Since we hold s.mu and haven't synchronized since checking done, if priority_semaphore_impl.go
105 > // ctx becomes done before we return here, it becoming done must have
106 > // "happened concurrently" with this call - it cannot "happen before"
107 > // we return in this branch. So, we're ok to always acquire here.
108 > s.cur += n
109 > s.mu.Unlock()
110 > return nil
111 > }
112
113 if n > s.size {
173 }
174
175 > func (s *PrioritySemaphoreImpl) Release(n int) { priority_semaphore_impl.go
176 > s.mu.Lock()
177 > defer s.mu.Unlock()
178 > s.cur -= n
179 > if s.cur < 0 {
180 s.mu.Unlock()
181 panic("semaphore: released more than held")
182 }
183 > s.notifyWaiters() priority_semaphore_impl.go
184 }
185
186 > func (s *PrioritySemaphoreImpl) notifyWaiters() { priority_semaphore_impl.go
187 > for _, l := range s.waitLists {
188 > for {
189 > next := l.Front()
190 > if next == nil {
191 > break // No more waiters blocked.
192 }
193
219
220 // noWaiters returns if there is no waiter that has priority higher or equal to lowestPriority.
221 > func (s *PrioritySemaphoreImpl) noWaiters(lowestPriority Priority) bool { priority_semaphore_impl.go
222 > for _, l := range s.waitLists[:lowestPriority+1] {
223 > if l.Len() > 0 {
224 return false
225 }
226 }
227 > return true priority_semaphore_impl.go
228 }
go.temporal.io/server/common/namespace/namespace.go 41 covered LOC · 15 ranges

Open complete file

81 resolver ReplicationResolver,
82 mutations ...Mutation,
83 > ) (*Namespace, error) { namespace.go
84 > if resolver == nil {
85 return nil, serviceerror.NewInvalidArgument("replicationResolver must be provided")
86 }
87 > ns := &Namespace{ namespace.go
88 > info: detail.Info,
89 > config: detail.Config,
90 > configVersion: detail.ConfigVersion,
91 > customSearchAttributesMapper: CustomSearchAttributesMapper{
92 > fieldToAlias: detail.Config.CustomSearchAttributeAliases,
93 > aliasToField: util.InverseMap(detail.Config.CustomSearchAttributeAliases),
94 > },
95 > replicationResolver: resolver,
96 > }
97 >
98 > for _, m := range mutations {
99 > m.apply(ns) namespace.go
100 > }
101
102 > return ns, nil namespace.go
103 }
104
159
160 // ID observes this namespace's permanent unique identifier in string form.
161 > func (ns *Namespace) ID() ID { namespace.go
162 > if ns.info == nil {
163 return ID("")
164 }
165 > return ID(ns.info.Id) namespace.go
166 }
167
168 // Name observes this namespace's configured name.
169 > func (ns *Namespace) Name() Name { namespace.go
170 > if ns.info == nil {
171 return Name("")
172 }
173 > return Name(ns.info.Name) namespace.go
174 }
175
176 > func (ns *Namespace) State() enumspb.NamespaceState { namespace.go
177 > if ns.info == nil {
178 return enumspb.NAMESPACE_STATE_UNSPECIFIED
179 }
180 > return ns.info.State namespace.go
181 }
182
219 // Being a global namespace doesn't necessarily mean that there are multiple registered clusters for it, only that it
220 // has a failover version. To determine whether operations should be replicated for a namespace, see ReplicationPolicy.
221 > func (ns *Namespace) IsGlobalNamespace() bool { namespace.go
222 > return ns.replicationResolver.IsGlobalNamespace()
223 > }
224
225 // FailoverNotificationVersion return the global notification version of when failover happened
256 // Note: Do not use this to determine if a workflow is active in the cluster.
257 // Use ActiveClusterName(businessID) instead.
258 > func (ns *Namespace) ActiveInCluster(clusterName string) bool { namespace.go
259 > return ns.replicationResolver.ActiveInCluster(clusterName)
260 > }
261
262 // ReplicationPolicy return the derived workflow replication policy
337 }
338
339 > func (id ID) String() string { namespace.go
340 > return string(id)
341 > }
342
343 func (id ID) IsEmpty() bool {
345 }
346
347 > func (n Name) String() string { namespace.go
348 > return string(n)
349 > }
350
351 > func (n Name) IsEmpty() bool { namespace.go
352 > return n == EmptyName
353 > }
354
355 func (m *CustomSearchAttributesMapper) GetAlias(fieldName string, namespace string) (string, error) {
go.temporal.io/server/common/primitives/uuid.go 41 covered LOC · 15 ranges

Open complete file

17 // returns nil if the input is empty string
18 // panics if the given input is malformed
19 > func MustParseUUID(s string) UUID { uuid.go
20 > if s == "" {
21 return nil
22 }
23 > u := guuid.MustParse(s) uuid.go
24 > return u[:]
25 }
26
30 // - error if input is malformed
31 // - UUID object if input can be parsed and is valid
32 > func ParseUUID(s string) (UUID, error) { uuid.go
33 > if s == "" {
34 > return nil, nil uuid.go
35 > }
36 > u, err := guuid.Parse(s) uuid.go
37 >
38 > if err != nil {
39 return nil, err
40 }
41 > return u[:], nil uuid.go
42 }
43
68
69 // NewUUID generates a new random UUID
70 > func NewUUID() UUID { uuid.go
71 > u, err := guuid.NewV7()
72 > if err != nil {
73 // Should never happen, but this matches the behavior of google/uuid.NewRandom
74 return nil
75 }
76 > return u[:] uuid.go
77 }
78
91 // String returns the 36 byte hexstring representation of this uuid
92 // return empty string if this uuid is nil
93 > func (u UUID) String() string { uuid.go
94 > if len(u) != 16 {
95 return ""
96 }
97 > var buf [36]byte uuid.go
98 > u.encodeHex(buf[:])
99 > return string(buf[:])
100 }
101
122 // Scan implements sql.Scanner interface to allow this type to be
123 // parsed transparently by database drivers
124 > func (u *UUID) Scan(src any) error { uuid.go
125 > if src == nil {
126 return nil
127 }
128 > guuid := &guuid.UUID{} uuid.go
129 > if err := guuid.Scan(src); err != nil {
130 return err
131 }
132 > *u = (*guuid)[:] uuid.go
133 > return nil
134 }
135
136 // Value implements sql.Valuer so that UUIDs can be written to databases
137 // transparently. This method returns a byte slice representation of uuid
138 > func (u UUID) Value() (driver.Value, error) { uuid.go
139 > return []byte(u), nil
140 > }
141
142 > func (u UUID) encodeHex(dst []byte) { uuid.go
143 > hex.Encode(dst, u[:4])
144 > dst[8] = '-'
145 > hex.Encode(dst[9:13], u[4:6])
146 > dst[13] = '-'
147 > hex.Encode(dst[14:18], u[6:8])
148 > dst[18] = '-'
149 > hex.Encode(dst[19:23], u[8:10])
150 > dst[23] = '-'
151 > hex.Encode(dst[24:], u[10:])
152 > }
go.temporal.io/server/service/history/replication/task_fetcher.go 41 covered LOC · 7 ranges

Open complete file

93 clusterMetadata cluster.Metadata,
94 clientBean client.Bean,
95 > ) TaskFetcherFactory { task_fetcher.go
96 > return &taskFetcherFactoryImpl{
97 > clusterMetadata: clusterMetadata,
98 > clientBean: clientBean,
99 > config: config,
100 > fetchers: make(map[string]taskFetcher),
101 > status: common.DaemonStatusInitialized,
102 > logger: logger,
103 > }
104 > }
105
106 // Start starts the fetchers
107 > func (f *taskFetcherFactoryImpl) Start() { task_fetcher.go
108 > if !atomic.CompareAndSwapInt32(
109 > &f.status,
110 > common.DaemonStatusInitialized,
111 > common.DaemonStatusStarted,
112 > ) {
113 return
114 }
115
116 > f.listenClusterMetadataChange() task_fetcher.go
117 > f.logger.Info("Replication task fetchers started.")
118 }
119
120 // Stop stops the fetchers
121 > func (f *taskFetcherFactoryImpl) Stop() { task_fetcher.go
122 > if !atomic.CompareAndSwapInt32(
123 > &f.status,
124 > common.DaemonStatusStarted,
125 > common.DaemonStatusStopped,
126 > ) {
127 return
128 }
129
130 > f.clusterMetadata.UnRegisterMetadataChangeCallback(f) task_fetcher.go
131 > f.fetchersLock.Lock()
132 > defer f.fetchersLock.Unlock()
133 > for _, fetcher := range f.fetchers {
134 fetcher.Stop()
135 }
136 > f.logger.Info("Replication task fetchers stopped.") task_fetcher.go
137 }
138
162 }
163
164 > func (f *taskFetcherFactoryImpl) listenClusterMetadataChange() { task_fetcher.go
165 > f.clusterMetadata.RegisterMetadataChangeCallback(
166 > f,
167 > func(oldClusterMetadata map[string]*cluster.ClusterInformation, newClusterMetadata map[string]*cluster.ClusterInformation) {
168 > f.fetchersLock.Lock()
169 > defer f.fetchersLock.Unlock()
170 >
171 > currentCluster := f.clusterMetadata.GetCurrentClusterName()
172 > // Fetcher is lazy init. The callback only need to handle remove case.
173 > for clusterName, newClusterInfo := range newClusterMetadata {
174 > if clusterName == currentCluster {
175 > continue
176 }
177 if fetcher, ok := f.fetchers[clusterName]; ok {
go.temporal.io/server/common/headers/version_checker.go 40 covered LOC · 11 ranges

Open complete file

76
77 // NewDefaultVersionChecker constructs a new VersionChecker using default versions from const.
78 > func NewDefaultVersionChecker() *versionChecker { version_checker.go
79 > return NewVersionChecker(SupportedClients, ServerVersion)
80 > }
81
82 // NewVersionChecker constructs a new VersionChecker
83 > func NewVersionChecker(supportedClients map[string]string, serverVersion string) *versionChecker { version_checker.go
84 > return &versionChecker{
85 > serverVersion: semver.MustParse(serverVersion),
86 > supportedClients: supportedClients,
87 > supportedClientsRange: mustParseRanges(supportedClients),
88 > }
89 > }
90
91 // GetClientNameAndVersion extracts SDK name and version from context headers
92 > func GetClientNameAndVersion(ctx context.Context) (string, string) { version_checker.go
93 > headers := GetValues(ctx, ClientNameHeaderName, ClientVersionHeaderName)
94 > clientName := headers[0]
95 > clientVersion := headers[1]
96 > return clientName, clientVersion
97 > }
98
99 // SetVersions sets headers for internal communications.
114
115 // ClientSupported returns an error if client is unsupported, nil otherwise.
116 > func (vc *versionChecker) ClientSupported(ctx context.Context) error { version_checker.go
117 >
118 > headers := GetValues(ctx, ClientNameHeaderName, ClientVersionHeaderName, SupportedServerVersionsHeaderName)
119 > clientName := headers[0]
120 > clientVersion := headers[1]
121 > supportedServerVersions := headers[2]
122 >
123 > // Validate client version only if it is provided and server knows about this client.
124 > if clientName != "" && clientVersion != "" {
125 > if supportedClientRange, ok := vc.supportedClientsRange[clientName]; ok { version_checker.go
126 > clientVersionParsed, parseErr := semver.Parse(clientVersion)
127 > if parseErr != nil {
128 return serviceerror.NewInvalidArgumentf("Unable to parse client version: %v", parseErr)
129 }
130 > if !supportedClientRange(clientVersionParsed) { version_checker.go
131 return serviceerror.NewClientVersionNotSupported(clientVersion, clientName, vc.supportedClients[clientName])
132 }
135
136 // Validate supported server version if it is provided.
137 > if supportedServerVersions != "" { version_checker.go
138 > supportedServerVersionsParsed, parseErr := semver.ParseRange(supportedServerVersions) version_checker.go
139 > if parseErr != nil {
140 return serviceerror.NewInvalidArgumentf("Unable to parse supported server versions: %v", parseErr)
141 }
142 > if !supportedServerVersionsParsed(vc.serverVersion) { version_checker.go
143 return serviceerror.NewServerVersionNotSupported(vc.serverVersion.String(), supportedServerVersions)
144 }
145 }
146
147 > return nil version_checker.go
148 }
149
163 }
164
165 > func mustParseRanges(ranges map[string]string) map[string]semver.Range { version_checker.go
166 > out := make(map[string]semver.Range, len(ranges))
167 > for c, r := range ranges {
168 > out[c] = semver.MustParseRange(r)
169 > }
170 > return out
171 }
go.temporal.io/server/common/metrics/grpc.go 40 covered LOC · 9 ranges

Open complete file

32 // NewServerMetricsContextInjectorInterceptor returns grpc server interceptor that adds metrics context to golang
33 // context.
34 > func NewServerMetricsContextInjectorInterceptor() grpc.UnaryServerInterceptor { grpc.go
35 > return func(
36 > ctx context.Context,
37 > req any,
38 > info *grpc.UnaryServerInfo,
39 > handler grpc.UnaryHandler,
40 > ) (any, error) {
41 > ctxWithMetricsBaggage := AddMetricsContext(ctx)
42 > return handler(ctxWithMetricsBaggage, req)
43 > }
44 }
45
46 // NewClientMetricsTrailerPropagatorInterceptor returns grpc client interceptor that injects metrics received in trailer
47 // into metrics context.
48 > func NewClientMetricsTrailerPropagatorInterceptor(logger log.Logger) grpc.UnaryClientInterceptor { grpc.go
49 > return func(
50 > ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker,
51 > opts ...grpc.CallOption,
52 > ) error {
53 var trailer metadata.MD
54 optsWithTrailer := append(opts, grpc.Trailer(&trailer))
79 // NewServerMetricsTrailerPropagatorInterceptor returns grpc server interceptor that injects metrics from context into
80 // gRPC trailer.
81 > func NewServerMetricsTrailerPropagatorInterceptor(logger log.Logger) grpc.UnaryServerInterceptor { grpc.go
82 > return func(
83 > ctx context.Context,
84 > req any,
85 > info *grpc.UnaryServerInfo,
86 > handler grpc.UnaryHandler,
87 > ) (any, error) {
88 // we want to return original handler response, so don't override err
89 resp, err := handler(ctx, req)
123
124 // getMetricsContext extracts metrics context from golang context.
125 > func getMetricsContext(ctx context.Context) *metricsContext { grpc.go
126 > metricsCtx := ctx.Value(metricsCtxKey)
127 > if metricsCtx == nil {
128 return nil
129 }
130
131 > return metricsCtx.(*metricsContext) grpc.go
132 }
133
134 > func AddMetricsContext(ctx context.Context) context.Context { grpc.go
135 > metricsCtx := &metricsContext{}
136 > return context.WithValue(ctx, metricsCtxKey, metricsCtx)
137 > }
138
139 // ContextCounterAdd adds value to counter within metrics context.
160
161 // ContextCounterGet returns value and true if successfully retrieved value
162 > func ContextCounterGet(ctx context.Context, name string) (int64, bool) { grpc.go
163 > metricsCtx := getMetricsContext(ctx)
164 >
165 > if metricsCtx == nil {
166 return 0, false
167 }
168
169 > metricsCtx.Lock() grpc.go
170 > defer metricsCtx.Unlock()
171 >
172 > if metricsCtx.CountersInt == nil {
173 > return 0, false grpc.go
174 > }
175
176 result, ok := metricsCtx.CountersInt[name]
go.temporal.io/server/common/quotas/rate_limiter_impl.go 40 covered LOC · 10 ranges

Open complete file

24 // NewRateLimiter returns a new rate limiter that can handle dynamic
25 // configuration updates
26 > func NewRateLimiter(newRPS float64, newBurst int) *RateLimiterImpl { rate_limiter_impl.go
27 > limiter := rate.NewLimiter(rate.Limit(newRPS), newBurst)
28 > ts := clock.NewRealTimeSource()
29 > rl := &RateLimiterImpl{
30 > rps: newRPS,
31 > burst: newBurst,
32 > timeSource: ts,
33 > ClockedRateLimiter: NewClockedRateLimiter(limiter, ts),
34 > }
35 >
36 > return rl
37 > }
38
39 // SetRPS sets the rate of the rate limiter
47 }
48
49 > func (rl *RateLimiterImpl) Reserve() Reservation { rate_limiter_impl.go
50 > return rl.ClockedRateLimiter.Reserve()
51 > }
52
53 > func (rl *RateLimiterImpl) ReserveN(now time.Time, n int) Reservation { rate_limiter_impl.go
54 > return rl.ClockedRateLimiter.ReserveN(now, n)
55 > }
56
57 // SetRateBurst sets the rps & burst of the rate limiter
58 > func (rl *RateLimiterImpl) SetRateBurst(rps float64, burst int) { rate_limiter_impl.go
59 > rl.refreshInternalRateLimiterImpl(&rps, &burst)
60 > }
61
62 // Rate returns the rps for this rate limiter
87 newRate *float64,
88 newBurst *int,
90 > rl.Lock()
91 > defer rl.Unlock()
92 >
93 > refresh := false
94 >
95 > if newRate != nil && rl.rps != *newRate {
96 > rl.rps = *newRate rate_limiter_impl.go
97 > refresh = true
98 > }
99
100 > if newBurst != nil && rl.burst != *newBurst { rate_limiter_impl.go
101 > rl.burst = *newBurst rate_limiter_impl.go
102 > refresh = true
103 > }
104
105 > if refresh { rate_limiter_impl.go
106 > now := rl.timeSource.Now() rate_limiter_impl.go
107 > rl.SetLimitAt(now, rate.Limit(rl.rps))
108 > rl.SetBurstAt(now, rl.burst)
109 > }
110 }
111
go.temporal.io/server/service/history/hsm/registry.go 39 covered LOC · 11 ranges

Open complete file

47
48 // NewRegistry creates a new [Registry].
49 > func NewRegistry() *Registry { registry.go
50 > return &Registry{
51 > machines: make(map[string]StateMachineDefinition),
52 > tasks: make(map[string]TaskSerializer),
53 > immediateExecutors: make(map[string]any),
54 > timerExecutors: make(map[string]any),
55 > remoteExecutors: make(map[string]remoteMethodDefinition),
56 > events: make(map[enumspb.EventType]EventDefinition),
57 > }
58 > }
59
60 // RegisterMachine registers a [StateMachineDefinition] by its type.
61 // Returns an [ErrDuplicateRegistration] if the state machine type has already been registered.
62 > func (r *Registry) RegisterMachine(sm StateMachineDefinition) error { registry.go
63 > t := sm.Type()
64 > if existing, ok := r.machines[t]; ok {
65 return fmt.Errorf("%w: state machine already registered for %v - %v", ErrDuplicateRegistration, sm.Type(), existing.Type())
66 }
67 > r.machines[t] = sm registry.go
68 > return nil
69 }
70
77 // RegisterTaskSerializer registers a [TaskSerializer] for a given type.
78 // Returns an [ErrDuplicateRegistration] if a serializer for this task type has already been registered.
79 > func (r *Registry) RegisterTaskSerializer(t string, def TaskSerializer) error { registry.go
80 > if exising, ok := r.tasks[t]; ok {
81 return fmt.Errorf("%w: task already registered for %v: %v", ErrDuplicateRegistration, t, exising)
82 }
83 > r.tasks[t] = def registry.go
84 > return nil
85 }
86
93 // RegisterImmediateExecutor registers an [ImmediateExecutor] for the given task type.
94 // Returns an [ErrDuplicateRegistration] if an executor for the type has already been registered.
95 > func RegisterImmediateExecutor[T Task](r *Registry, executor ImmediateExecutor[T]) error { registry.go
96 > var task T
97 > taskType := task.Type()
98 > // The executors are registered in pairs, so only need to check in one map.
99 > if existing, ok := r.immediateExecutors[taskType]; ok {
100 return fmt.Errorf(
101 "%w: executor already registered for task type %v: %v",
105 )
106 }
107 > r.immediateExecutors[taskType] = executor registry.go
108 > return nil
109 }
110
131 // RegisterTimerExecutor registers a [TimerExecutor] for the given task type.
132 // Returns an [ErrDuplicateRegistration] if an executor for the type has already been registered.
133 > func RegisterTimerExecutor[T Task](r *Registry, executor TimerExecutor[T]) error { registry.go
134 > var task T
135 > taskType := task.Type()
136 > // The executors are registered in pairs, so only need to check in one map.
137 > if existing, ok := r.timerExecutors[taskType]; ok {
138 return fmt.Errorf(
139 "%w: executor already registered for task type %v: %v",
143 )
144 }
145 > r.timerExecutors[taskType] = executor registry.go
146 > return nil
147 }
148
262 // RegisterEventDefinition registers an [EventDefinition] for the given event type.
263 // Returns an [ErrDuplicateRegistration] if a definition for the type has already been registered.
264 > func (r *Registry) RegisterEventDefinition(def EventDefinition) error { registry.go
265 > t := def.Type()
266 > prev, ok := r.events[t]
267 > if ok {
268 return fmt.Errorf("%w: event definition for event type %v: %v", ErrDuplicateRegistration, t, prev)
269 }
270 > r.events[t] = def registry.go
271 > return nil
272 }
273
go.temporal.io/server/service/history/shard/context_factory.go 39 covered LOC · 3 ranges

Open complete file

74 )
75
76 > func ContextFactoryProvider(params ContextFactoryParams) ContextFactory { context_factory.go
77 > return &contextFactoryImpl{
78 > ContextFactoryParams: &params,
79 > }
80 > }
81
82 func (c *contextFactoryImpl) CreateContext(
83 shardID int32,
84 closeCallback CloseCallback,
85 > ) (historyi.ControllableContext, error) { context_factory.go
86 > shard, err := newContext(
87 > shardID,
88 > c.EngineFactory,
89 > c.Config,
90 > c.PersistenceConfig,
91 > closeCallback,
92 > c.Logger,
93 > c.ThrottledLogger,
94 > c.PersistenceExecutionManager,
95 > c.PersistenceShardManager,
96 > c.ClientBean,
97 > c.HistoryClient,
98 > c.MetricsHandler,
99 > c.EventLogger,
100 > c.PayloadSerializer,
101 > c.TimeSource,
102 > c.NamespaceRegistry,
103 > c.SaProvider,
104 > c.SaMapperProvider,
105 > c.ClusterMetadata,
106 > c.ArchivalMetadata,
107 > c.HostInfoProvider,
108 > c.TaskCategoryRegistry,
109 > c.EventsCache,
110 > c.StateMachineRegistry,
111 > c.ChasmRegistry,
112 > c.ChasmWorkflowRegistry,
113 > c.EndpointRegistry,
114 > c.HandoverTrackerFactory,
115 > )
116 > if err != nil {
117 return nil, err
118 }
119 > shard.start() context_factory.go
120 > return shard, nil
121 }
go.temporal.io/server/chasm/lib/tests/library.go 38 covered LOC · 5 ranges

Open complete file

24 var Library = &library{}
25
26 > func (l *library) Name() string { library.go
27 > return libraryName
28 > }
29
30 > func (l *library) NexusServices() []*nexus.Service { library.go
31 > return []*nexus.Service{NewTestServiceNexusService()}
32 > }
33
34 > func (l *library) NexusServiceProcessors() []*chasm.NexusServiceProcessor { library.go
35 > return []*chasm.NexusServiceProcessor{NewTestServiceNexusServiceProcessor()}
36 > }
37
38 > func (l *library) Components() []*chasm.RegistrableComponent { library.go
39 > return []*chasm.RegistrableComponent{
40 > chasm.NewRegistrableComponent[*PayloadStore](
41 > componentName,
42 > chasm.WithBusinessIDAlias("PayloadStoreId"),
43 > chasm.WithSearchAttributes(
44 > PayloadTotalCountSearchAttribute,
45 > PayloadTotalSizeSearchAttribute,
46 > ExecutionStatusSearchAttribute,
47 > chasm.SearchAttributeTaskQueue,
48 > ),
49 > chasm.WithContextValues(map[any]any{
50 > componentCtxKey: componentCtxVal,
51 > }),
52 > ),
53 > }
54 > }
55
56 > func (l *library) Tasks() []*chasm.RegistrableTask { library.go
57 > return []*chasm.RegistrableTask{
58 > chasm.NewRegistrablePureTask(
59 > "payloadTTLPureTask",
60 > &PayloadTTLPureTaskHandler{},
61 > ),
62 > chasm.NewRegistrableSideEffectTask(
63 > "payloadTTLSideEffectTask",
64 > &PayloadTTLSideEffectTaskHandler{},
65 > ),
66 > }
67 > }
go.temporal.io/server/common/cache/lru.go 38 covered LOC · 10 ranges

Open complete file

135
136 // New creates a new cache with the given options
137 > func New(maxSize int, opts *Options) StoppableCache { lru.go
138 > return NewWithMetrics(maxSize, opts, metrics.NoopMetricsHandler)
139 > }
140
141 // NewWithMetrics creates a new cache that will emit capacity and ttl metrics.
142 // handler should be tagged with metrics.CacheTypeTag.
143 > func NewWithMetrics(maxSize int, opts *Options, handler metrics.Handler) StoppableCache { lru.go
144 > if opts == nil {
145 > opts = &Options{} lru.go
146 > }
147
148 > backgroundEvict := opts.BackgroundEvict lru.go
149 > if backgroundEvict == nil {
150 > backgroundEvict = func() dynamicconfig.CacheBackgroundEvictSettings { lru.go
151 > return dynamicconfig.CacheBackgroundEvictSettings{
152 > Enabled: false,
153 > }
154 > }
155 }
156
157 > timeSource := opts.TimeSource lru.go
158 > if timeSource == nil {
159 > timeSource = clock.NewRealTimeSource() lru.go
160 > }
161
162 > metrics.CacheSize.With(handler).Record(float64(maxSize)) lru.go
163 > metrics.CacheTtl.With(handler).Record(opts.TTL)
164 > c := &lru{
165 > byAccess: list.New(),
166 > byKey: make(map[any]*list.Element),
167 > ttl: opts.TTL,
168 > maxSize: maxSize,
169 > currSize: 0,
170 > pin: opts.Pin,
171 > onPut: opts.OnPut,
172 > onEvict: opts.OnEvict,
173 > timeSource: timeSource,
174 > metricsHandler: handler,
175 > backgroundEvict: backgroundEvict,
176 > }
177 > if c.backgroundEvict().Enabled {
178 c.loops.Go(c.bgEvictLoop)
179 }
180 > return c lru.go
181 }
182
446 }
447
448 > func (c *lru) Stop() { lru.go
449 > c.loops.Cancel()
450 > }
451
452 func (c *lru) bgEvictLoop(ctx context.Context) error {
go.temporal.io/server/common/timer/local_gate.go 38 covered LOC · 10 ranges

Open complete file

27
28 // NewLocalGate create a new timer gate instance
29 > func NewLocalGate(timeSource clock.TimeSource) LocalGate { local_gate.go
30 > lg := &LocalGateImpl{
31 > timer: time.NewTimer(0),
32 > nextWakeupTime: time.Time{},
33 > fireCh: make(chan struct{}, 1),
34 > closeCh: make(chan struct{}),
35 > timeSource: timeSource,
36 > }
37 > // the timer should be stopped when initialized
38 > if !lg.timer.Stop() {
39 // drain the existing signal if exist
40 <-lg.timer.C
41 }
42
43 > go func() { local_gate.go
44 > defer close(lg.fireCh)
45 > defer lg.timer.Stop()
46 > loop:
47 > for {
48 > select {
49 > case <-lg.timer.C: local_gate.go
50 > select {
51 // re-transmit on gateC
52 > case lg.fireCh <- struct{}{}: local_gate.go
53 default:
54 }
55
56 > case <-lg.closeCh: local_gate.go
57 > // closed; cleanup and quit
58 > break loop
59 }
60 }
61 }()
62
63 > return lg local_gate.go
64 }
65
66 // FireCh return the channel which will be fired when time is up
67 > func (lg *LocalGateImpl) FireCh() <-chan struct{} { local_gate.go
68 > return lg.fireCh
69 > }
70
71 // FireAfter check will the timer get fired after a certain time
76 // Update the timer gate, return true if update is a success.
77 // Success means timer is idle or timer is set with a sooner time to fire
78 > func (lg *LocalGateImpl) Update(nextTime time.Time) bool { local_gate.go
79 > // NOTE: negative duration will make the timer fire immediately
80 > now := lg.timeSource.Now()
81 >
82 > if lg.timer.Stop() && lg.nextWakeupTime.Before(nextTime) {
83 // this means the timer, before stopped, is active && next wake-up time do not have to be updated
84 lg.timer.Reset(lg.nextWakeupTime.Sub(now))
88 // this means the timer, before stopped, is active && next wake-up time has to be updated
89 // or this means the timer, before stopped, is already fired / never active
90 > lg.nextWakeupTime = nextTime local_gate.go
91 > lg.timer.Reset(nextTime.Sub(now))
92 > // Notifies caller that next notification is reset to fire at passed in 'next' visibility time
93 > return true
94 }
95
96 // Close shutdown the timer
97 > func (lg *LocalGateImpl) Close() { local_gate.go
98 > close(lg.closeCh)
99 > }
go.temporal.io/server/common/util/util.go 38 covered LOC · 16 ranges

Open complete file

20
21 // MaxTime returns the latest of the given time.Time values.
22 > func MaxTime(first time.Time, rest ...time.Time) time.Time { util.go
23 > latest := first
24 > for _, t := range rest {
25 > if t.After(latest) {
26 > latest = t util.go
27 > }
28 }
29 > return latest util.go
30 }
31
68
69 // InverseMap creates the inverse map, ie., for a key-value map, it builds the value-key map.
70 > func InverseMap[M ~map[K]V, K, V comparable](m M) map[V]K { util.go
71 > if m == nil {
72 > return nil
73 > }
74 invm := make(map[V]K, len(m))
75 for k, v := range m {
133
134 // MapSlice given slice xs []T and f(T) S produces slice []S by applying f to every element of xs
135 > func MapSlice[T, S any](xs []T, f func(T) S) []S { util.go
136 > if xs == nil {
137 return nil
138 }
139 > result := make([]S, len(xs)) util.go
140 > for i, s := range xs {
141 > result[i] = f(s) util.go
142 > }
143 > return result util.go
144 }
145
146 // FilterSlice iterates over elements of a slice, returning a new slice of all elements predicate returns true for.
147 > func FilterSlice[T any](in []T, predicate func(T) bool) []T { util.go
148 > var out []T
149 > for _, elem := range in {
150 > if predicate(elem) { util.go
151 > out = append(out, elem) util.go
152 > }
153 }
154 > return out util.go
155 }
156
166 // RepeatSlice given slice and a number (n) produces a new slice containing original slice n times
167 // if n is non-positive will produce nil
168 > func RepeatSlice[T any](xs []T, n int) []T { util.go
169 > if xs == nil || n <= 0 {
170 return nil
171 }
172 > ys := make([]T, n*len(xs)) util.go
173 > for i := range n {
174 > copy(ys[i*len(xs):], xs)
175 > }
176 > return ys
177 }
178
186 // InterruptibleSleep is like time.Sleep but can be interrupted by a context.
187 // Returns context error if interrupted, otherwise nil.
188 > func InterruptibleSleep(ctx context.Context, timeout time.Duration) error { util.go
189 > timer := time.NewTimer(timeout)
190 > defer timer.Stop()
191 > select {
192 case <-timer.C:
193 return nil
194 > case <-ctx.Done(): util.go
195 > return ctx.Err()
196 }
197 }
go.temporal.io/server/service/worker/dlq/workflow.go 38 covered LOC · 5 ranges

Open complete file

192 )
193
194 > func newComponent(params workerComponentParams) workercommon.WorkerComponent { workflow.go
195 > return &workerComponent{
196 > historyClient: params.HistoryClient,
197 > currentClusterName: string(params.CurrentClusterName),
198 > taskClientDialer: params.TaskClientDialer,
199 > }
200 > }
201
202 //revive:disable:import-shadowing this doesn't actually shadow imports because it's a method, not a function
449 }
450
451 > func (c *workerComponent) RegisterWorkflow(registry sdkworker.Registry) { workflow.go
452 > registry.RegisterWorkflowWithOptions(c.workflow, workflow.RegisterOptions{
453 > Name: WorkflowName,
454 > })
455 > }
456
457 > func (c *workerComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { workflow.go
458 > // use default worker
459 > return nil
460 > }
461
462 > func (c *workerComponent) RegisterActivities(registry sdkworker.Registry) { workflow.go
463 > registry.RegisterActivityWithOptions(c.deleteTasks, activity.RegisterOptions{
464 > Name: deleteTasksActivityName,
465 > })
466 > registry.RegisterActivityWithOptions(c.readTasks, activity.RegisterOptions{
467 > Name: readTasksActivityName,
468 > })
469 > registry.RegisterActivityWithOptions(c.reEnqueueTasks, activity.RegisterOptions{
470 > Name: reEnqueueTasksActivityName,
471 > })
472 > }
473
474 > func (c *workerComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { workflow.go
475 > return &workercommon.DedicatedWorkerOptions{
476 > TaskQueue: primitives.DLQActivityTQ,
477 > Options: sdkworker.Options{
478 > BackgroundActivityContext: headers.SetCallerType(
479 > context.Background(),
480 > headers.CallerTypePreemptable,
481 > ),
482 > },
483 > }
484 > }
485
486 // Dial implements [TaskClientDialer] by calling the [TaskClientDialerFn] with the cluster name.
go.temporal.io/server/api/persistence/v1/chasm.pb.go 37 covered LOC · 3 ranges

Open complete file

571 func (*ChasmTaskInfo) ProtoMessage() {}
572
573 > func (x *ChasmTaskInfo) ProtoReflect() protoreflect.Message { chasm.pb.go
574 > mi := &file_temporal_server_api_persistence_v1_chasm_proto_msgTypes[8]
575 > if x != nil {
576 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
577 if ms.LoadMessageInfo() == nil {
580 return ms
581 }
582 > return mi.MessageOf(x) chasm.pb.go
583 }
584
1180 }
1181
1182 > func init() { file_temporal_server_api_persistence_v1_chasm_proto_init() } chasm.pb.go
1183 > func file_temporal_server_api_persistence_v1_chasm_proto_init() {
1184 > if File_temporal_server_api_persistence_v1_chasm_proto != nil {
1185 > return
1186 > }
1187 > file_temporal_server_api_persistence_v1_hsm_proto_init()
1188 > file_temporal_server_api_persistence_v1_chasm_proto_msgTypes[1].OneofWrappers = []any{
1189 > (*ChasmNodeMetadata_ComponentAttributes)(nil),
1190 > (*ChasmNodeMetadata_DataAttributes)(nil),
1191 > (*ChasmNodeMetadata_CollectionAttributes)(nil),
1192 > (*ChasmNodeMetadata_PointerAttributes)(nil),
1193 > }
1194 > file_temporal_server_api_persistence_v1_chasm_proto_msgTypes[10].OneofWrappers = []any{
1195 > (*ChasmNexusCompletion_Success)(nil),
1196 > (*ChasmNexusCompletion_Failure)(nil),
1197 > }
1198 > type x struct{}
1199 > out := protoimpl.TypeBuilder{
1200 > File: protoimpl.DescBuilder{
1201 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1202 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_chasm_proto_rawDesc), len(file_temporal_server_api_persistence_v1_chasm_proto_rawDesc)),
1203 > NumEnums: 0,
1204 > NumMessages: 15,
1205 > NumExtensions: 0,
1206 > NumServices: 0,
1207 > },
1208 > GoTypes: file_temporal_server_api_persistence_v1_chasm_proto_goTypes,
1209 > DependencyIndexes: file_temporal_server_api_persistence_v1_chasm_proto_depIdxs,
1210 > MessageInfos: file_temporal_server_api_persistence_v1_chasm_proto_msgTypes,
1211 > }.Build()
1212 > File_temporal_server_api_persistence_v1_chasm_proto = out.File
1213 > file_temporal_server_api_persistence_v1_chasm_proto_goTypes = nil
1214 > file_temporal_server_api_persistence_v1_chasm_proto_depIdxs = nil
1215 }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/shard.go 37 covered LOC · 5 ranges

Open complete file

28 ctx context.Context,
29 row *sqlplugin.ShardsRow,
30 > ) (sql.Result, error) { shard.go
31 > return mdb.conn.ExecContext(ctx,
32 > createShardQry,
33 > row.ShardID,
34 > row.RangeID,
35 > row.Data,
36 > row.DataEncoding,
37 > )
38 > }
39
40 // UpdateShards updates one or more rows into shards table
42 ctx context.Context,
43 row *sqlplugin.ShardsRow,
44 > ) (sql.Result, error) { shard.go
45 > return mdb.conn.ExecContext(ctx,
46 > updateShardQry,
47 > row.RangeID,
48 > row.Data,
49 > row.DataEncoding,
50 > row.ShardID,
51 > )
52 > }
53
54 // SelectFromShards reads one or more rows from shards table
56 ctx context.Context,
57 filter sqlplugin.ShardsFilter,
58 > ) (*sqlplugin.ShardsRow, error) { shard.go
59 > var row sqlplugin.ShardsRow
60 > err := mdb.conn.GetContext(ctx,
61 > &row,
62 > getShardQry,
63 > filter.ShardID,
64 > )
65 > if err != nil {
66 > return nil, err shard.go
67 > }
68 return &row, err
69 }
87 ctx context.Context,
88 filter sqlplugin.ShardsFilter,
89 > ) (int64, error) { shard.go
90 > var rangeID int64
91 > err := mdb.conn.GetContext(ctx,
92 > &rangeID,
93 > lockShardQry,
94 > filter.ShardID,
95 > )
96 > return rangeID, err
97 > }
go.temporal.io/server/components/nexusoperations/events.go 37 covered LOC · 18 ranges

Open complete file

17 }
18
19 > func (d ScheduledEventDefinition) Type() enumspb.EventType { events.go
20 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED
21 > }
22
23 func (d ScheduledEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
41 }
42
43 > func (d CancelRequestedEventDefinition) Type() enumspb.EventType { events.go
44 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED
45 > }
46
47 func (d CancelRequestedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
64 }
65
66 > func (d CancelRequestCompletedEventDefinition) Type() enumspb.EventType { events.go
67 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_COMPLETED
68 > }
69
70 func (d CancelRequestCompletedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
98 }
99
100 > func (d CancelRequestFailedEventDefinition) Type() enumspb.EventType { events.go
101 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED
102 > }
103
104 func (d CancelRequestFailedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
133 }
134
135 > func (d StartedEventDefinition) Type() enumspb.EventType { events.go
136 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_STARTED
137 > }
138
139 func (d StartedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
176 }
177
178 > func (d CompletedEventDefinition) Type() enumspb.EventType { events.go
179 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_COMPLETED
180 > }
181
182 func (d CompletedEventDefinition) CherryPick(root *hsm.Node, event *historypb.HistoryEvent, excludeTypes map[enumspb.ResetReapplyExcludeType]struct{}) error {
193 }
194
195 > func (d FailedEventDefinition) Type() enumspb.EventType { events.go
196 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_FAILED
197 > }
198
199 func (d FailedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
225 }
226
227 > func (d CanceledEventDefinition) Type() enumspb.EventType { events.go
228 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCELED
229 > }
230
231 func (d CanceledEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
256 }
257
258 > func (d TimedOutEventDefinition) Type() enumspb.EventType { events.go
259 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_TIMED_OUT
260 > }
261
262 func (d TimedOutEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
280 }
281
282 > func RegisterEventDefinitions(reg *hsm.Registry) error { events.go
283 > if err := reg.RegisterEventDefinition(ScheduledEventDefinition{}); err != nil {
284 return err
285 }
286 > if err := reg.RegisterEventDefinition(CancelRequestedEventDefinition{}); err != nil { events.go
287 return err
288 }
289 > if err := reg.RegisterEventDefinition(CancelRequestCompletedEventDefinition{}); err != nil { events.go
290 return err
291 }
292 > if err := reg.RegisterEventDefinition(CancelRequestFailedEventDefinition{}); err != nil { events.go
293 return err
294 }
295 > if err := reg.RegisterEventDefinition(StartedEventDefinition{}); err != nil { events.go
296 return err
297 }
298 > if err := reg.RegisterEventDefinition(CompletedEventDefinition{}); err != nil { events.go
299 return err
300 }
301 > if err := reg.RegisterEventDefinition(FailedEventDefinition{}); err != nil { events.go
302 return err
303 }
304 > if err := reg.RegisterEventDefinition(CanceledEventDefinition{}); err != nil { events.go
305 return err
306 }
307 > return reg.RegisterEventDefinition(TimedOutEventDefinition{}) events.go
308 }
309
go.temporal.io/server/service/frontend/operator_handler.go 37 covered LOC · 3 ranges

Open complete file

92 func NewOperatorHandlerImpl(
93 args NewOperatorHandlerImplArgs,
94 > ) *OperatorHandlerImpl { operator_handler.go
95 >
96 > handler := &OperatorHandlerImpl{
97 > logger: args.Logger,
98 > status: common.DaemonStatusInitialized,
99 > config: args.config,
100 > sdkClientFactory: args.sdkClientFactory,
101 > metricsHandler: args.MetricsHandler,
102 > visibilityMgr: args.VisibilityMgr,
103 > saManager: args.SaManager,
104 > healthServer: args.healthServer,
105 > historyClient: args.historyClient,
106 > clusterMetadataManager: args.clusterMetadataManager,
107 > clusterMetadata: args.clusterMetadata,
108 > clientFactory: args.clientFactory,
109 > namespaceRegistry: args.namespaceRegistry,
110 > nexusEndpointClient: args.nexusEndpointClient,
111 > }
112 >
113 > return handler
114 > }
115
116 // Start starts the handler
117 > func (h *OperatorHandlerImpl) Start() { operator_handler.go
118 > if atomic.CompareAndSwapInt32(
119 > &h.status,
120 > common.DaemonStatusInitialized,
121 > common.DaemonStatusStarted,
122 > ) {
123 > h.healthServer.SetServingStatus(OperatorServiceName, healthpb.HealthCheckResponse_SERVING)
124 > }
125 }
126
127 // Stop stops the handler
128 > func (h *OperatorHandlerImpl) Stop() { operator_handler.go
129 > if atomic.CompareAndSwapInt32(
130 > &h.status,
131 > common.DaemonStatusStarted,
132 > common.DaemonStatusStopped,
133 > ) {
134 > h.healthServer.SetServingStatus(OperatorServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
135 > }
136 }
137
go.temporal.io/server/api/adminservice/v1/request_response.pb.go 36 covered LOC · 1 range

Open complete file

6623 }
6624
6625 > func init() { file_temporal_server_api_adminservice_v1_request_response_proto_init() } request_response.pb.go
6626 > func file_temporal_server_api_adminservice_v1_request_response_proto_init() {
6627 > if File_temporal_server_api_adminservice_v1_request_response_proto != nil {
6628 > return
6629 > }
6630 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[59].OneofWrappers = []any{
6631 > (*StreamWorkflowReplicationMessagesRequest_SyncReplicationState)(nil),
6632 > }
6633 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[60].OneofWrappers = []any{
6634 > (*StreamWorkflowReplicationMessagesResponse_Messages)(nil),
6635 > }
6636 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[61].OneofWrappers = []any{
6637 > (*GetNamespaceRequest_Namespace)(nil),
6638 > (*GetNamespaceRequest_Id)(nil),
6639 > }
6640 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[90].OneofWrappers = []any{
6641 > (*StartAdminBatchOperationRequest_RefreshTasksOperation)(nil),
6642 > }
6643 > type x struct{}
6644 > out := protoimpl.TypeBuilder{
6645 > File: protoimpl.DescBuilder{
6646 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
6647 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_adminservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_adminservice_v1_request_response_proto_rawDesc)),
6648 > NumEnums: 1,
6649 > NumMessages: 105,
6650 > NumExtensions: 0,
6651 > NumServices: 0,
6652 > },
6653 > GoTypes: file_temporal_server_api_adminservice_v1_request_response_proto_goTypes,
6654 > DependencyIndexes: file_temporal_server_api_adminservice_v1_request_response_proto_depIdxs,
6655 > EnumInfos: file_temporal_server_api_adminservice_v1_request_response_proto_enumTypes,
6656 > MessageInfos: file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes,
6657 > }.Build()
6658 > File_temporal_server_api_adminservice_v1_request_response_proto = out.File
6659 > file_temporal_server_api_adminservice_v1_request_response_proto_goTypes = nil
6660 > file_temporal_server_api_adminservice_v1_request_response_proto_depIdxs = nil
6661 }
go.temporal.io/server/api/replication/v1/message.pb.go 36 covered LOC · 2 ranges

Open complete file

2441 }
2442
2443 > func init() { file_temporal_server_api_replication_v1_message_proto_init() } message.pb.go
2444 > func file_temporal_server_api_replication_v1_message_proto_init() {
2445 > if File_temporal_server_api_replication_v1_message_proto != nil {
2446 return
2447 }
2448 > file_temporal_server_api_replication_v1_message_proto_msgTypes[0].OneofWrappers = []any{ message.pb.go
2449 > (*ReplicationTask_NamespaceTaskAttributes)(nil),
2450 > (*ReplicationTask_SyncShardStatusTaskAttributes)(nil),
2451 > (*ReplicationTask_SyncActivityTaskAttributes)(nil),
2452 > (*ReplicationTask_HistoryTaskAttributes)(nil),
2453 > (*ReplicationTask_SyncWorkflowStateTaskAttributes)(nil),
2454 > (*ReplicationTask_TaskQueueUserDataAttributes)(nil),
2455 > (*ReplicationTask_SyncHsmAttributes)(nil),
2456 > (*ReplicationTask_BackfillHistoryTaskAttributes)(nil),
2457 > (*ReplicationTask_VerifyVersionedTransitionTaskAttributes)(nil),
2458 > (*ReplicationTask_SyncVersionedTransitionTaskAttributes)(nil),
2459 > }
2460 > file_temporal_server_api_replication_v1_message_proto_msgTypes[21].OneofWrappers = []any{
2461 > (*VersionedTransitionArtifact_SyncWorkflowStateMutationAttributes)(nil),
2462 > (*VersionedTransitionArtifact_SyncWorkflowStateSnapshotAttributes)(nil),
2463 > }
2464 > type x struct{}
2465 > out := protoimpl.TypeBuilder{
2466 > File: protoimpl.DescBuilder{
2467 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
2468 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_replication_v1_message_proto_rawDesc), len(file_temporal_server_api_replication_v1_message_proto_rawDesc)),
2469 > NumEnums: 0,
2470 > NumMessages: 23,
2471 > NumExtensions: 0,
2472 > NumServices: 0,
2473 > },
2474 > GoTypes: file_temporal_server_api_replication_v1_message_proto_goTypes,
2475 > DependencyIndexes: file_temporal_server_api_replication_v1_message_proto_depIdxs,
2476 > MessageInfos: file_temporal_server_api_replication_v1_message_proto_msgTypes,
2477 > }.Build()
2478 > File_temporal_server_api_replication_v1_message_proto = out.File
2479 > file_temporal_server_api_replication_v1_message_proto_goTypes = nil
2480 > file_temporal_server_api_replication_v1_message_proto_depIdxs = nil
2481 }
go.temporal.io/server/common/namespace/testconstructors.go 36 covered LOC · 8 ranges

Open complete file

13 config *persistencespb.NamespaceConfig,
14 targetCluster string,
15 > ) *Namespace { testconstructors.go
16 > detail := &persistencespb.NamespaceDetail{
17 > Info: ensureInfo(info),
18 > Config: ensureConfig(config),
19 > ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
20 > ActiveClusterName: targetCluster,
21 > Clusters: []string{targetCluster},
22 > },
23 > FailoverVersion: common.EmptyVersion,
24 > }
25 > factory := NewDefaultReplicationResolverFactory()
26 > resolver := factory(detail)
27 > ns, _ := FromPersistentState(detail, resolver, WithGlobalFlag(false))
28 > return ns
29 > }
30
31 // NewNamespaceForTest returns an entry with test data
55 repConfig *persistencespb.NamespaceReplicationConfig,
56 failoverVersion int64,
57 > ) *Namespace { testconstructors.go
58 > detail := &persistencespb.NamespaceDetail{
59 > Info: ensureInfo(info),
60 > Config: ensureConfig(config),
61 > ReplicationConfig: ensureRepConfig(repConfig),
62 > FailoverVersion: failoverVersion,
63 > }
64 > factory := NewDefaultReplicationResolverFactory()
65 > resolver := factory(detail)
66 > ns, _ := FromPersistentState(detail, resolver, WithGlobalFlag(true))
67 > return ns
68 > }
69
70 > func ensureInfo(proto *persistencespb.NamespaceInfo) *persistencespb.NamespaceInfo { testconstructors.go
71 > if proto == nil {
72 return &persistencespb.NamespaceInfo{}
73 }
74 > return proto testconstructors.go
75 }
76
77 > func ensureConfig(proto *persistencespb.NamespaceConfig) *persistencespb.NamespaceConfig { testconstructors.go
78 > if proto == nil {
79 return &persistencespb.NamespaceConfig{}
80 }
81 > return proto testconstructors.go
82 }
83
84 > func ensureRepConfig(proto *persistencespb.NamespaceReplicationConfig) *persistencespb.NamespaceReplicationConfig { testconstructors.go
85 > if proto == nil {
86 return &persistencespb.NamespaceReplicationConfig{}
87 }
88 > return proto testconstructors.go
89 }
go.temporal.io/server/common/quotas/clocked_rate_limiter.go 36 covered LOC · 11 ranges

Open complete file

25 )
26
27 > func NewClockedRateLimiter(rateLimiter *rate.Limiter, timeSource clock.TimeSource) ClockedRateLimiter { clocked_rate_limiter.go
28 > return ClockedRateLimiter{
29 > rateLimiter: rateLimiter,
30 > timeSource: timeSource,
31 > recycleCh: make(chan struct{}),
32 > }
33 > }
34
35 > func (l ClockedRateLimiter) Allow() bool { clocked_rate_limiter.go
36 > return l.AllowN(l.timeSource.Now(), 1)
37 > }
38
39 > func (l ClockedRateLimiter) AllowN(now time.Time, token int) bool { clocked_rate_limiter.go
40 > return l.rateLimiter.AllowN(now, token)
41 > }
42
43 // ClockedReservation wraps a rate.Reservation with a clockwork.Clock. It is used to ensure that the reservation
48 }
49
50 > func (r ClockedReservation) OK() bool { clocked_rate_limiter.go
51 > return r.reservation.OK()
52 > }
53
54 > func (r ClockedReservation) Delay() time.Duration { clocked_rate_limiter.go
55 > return r.DelayFrom(r.timeSource.Now())
56 > }
57
58 > func (r ClockedReservation) DelayFrom(t time.Time) time.Duration { clocked_rate_limiter.go
59 > return r.reservation.DelayFrom(t)
60 > }
61
62 func (r ClockedReservation) Cancel() {
68 }
69
70 > func (l ClockedRateLimiter) Reserve() ClockedReservation { clocked_rate_limiter.go
71 > return l.ReserveN(l.timeSource.Now(), 1)
72 > }
73
74 > func (l ClockedRateLimiter) ReserveN(now time.Time, token int) ClockedReservation { clocked_rate_limiter.go
75 > reservation := l.rateLimiter.ReserveN(now, token)
76 > return ClockedReservation{reservation, l.timeSource}
77 > }
78
79 func (l ClockedRateLimiter) Wait(ctx context.Context) error {
142 }
143
144 > func (l ClockedRateLimiter) SetLimitAt(t time.Time, newLimit rate.Limit) { clocked_rate_limiter.go
145 > l.rateLimiter.SetLimitAt(t, newLimit)
146 > }
147
148 > func (l ClockedRateLimiter) SetBurstAt(t time.Time, newBurst int) { clocked_rate_limiter.go
149 > // Clamp burst to >=1 when rate is positive; burst=0 with rate=0 is allowed for pause.
150 > if newBurst < 1 && l.rateLimiter.Limit() > 0 {
151 newBurst = 1
152 }
153 > l.rateLimiter.SetBurstAt(t, newBurst) clocked_rate_limiter.go
154 }
155
go.temporal.io/server/api/persistence/v1/update.pb.go 35 covered LOC · 3 ranges

Open complete file

222 func (*UpdateInfo) ProtoMessage() {}
223
224 > func (x *UpdateInfo) ProtoReflect() protoreflect.Message { update.pb.go
225 > mi := &file_temporal_server_api_persistence_v1_update_proto_msgTypes[3]
226 > if x != nil {
227 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
228 if ms.LoadMessageInfo() == nil {
231 return ms
232 }
233 > return mi.MessageOf(x) update.pb.go
234 }
235
422 }
423
424 > func init() { file_temporal_server_api_persistence_v1_update_proto_init() } update.pb.go
425 > func file_temporal_server_api_persistence_v1_update_proto_init() {
426 > if File_temporal_server_api_persistence_v1_update_proto != nil {
427 > return
428 > }
429 > file_temporal_server_api_persistence_v1_hsm_proto_init()
430 > file_temporal_server_api_persistence_v1_update_proto_msgTypes[0].OneofWrappers = []any{
431 > (*UpdateAdmissionInfo_HistoryPointer_)(nil),
432 > }
433 > file_temporal_server_api_persistence_v1_update_proto_msgTypes[3].OneofWrappers = []any{
434 > (*UpdateInfo_Acceptance)(nil),
435 > (*UpdateInfo_Completion)(nil),
436 > (*UpdateInfo_Admission)(nil),
437 > }
438 > type x struct{}
439 > out := protoimpl.TypeBuilder{
440 > File: protoimpl.DescBuilder{
441 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
442 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_update_proto_rawDesc), len(file_temporal_server_api_persistence_v1_update_proto_rawDesc)),
443 > NumEnums: 0,
444 > NumMessages: 5,
445 > NumExtensions: 0,
446 > NumServices: 0,
447 > },
448 > GoTypes: file_temporal_server_api_persistence_v1_update_proto_goTypes,
449 > DependencyIndexes: file_temporal_server_api_persistence_v1_update_proto_depIdxs,
450 > MessageInfos: file_temporal_server_api_persistence_v1_update_proto_msgTypes,
451 > }.Build()
452 > File_temporal_server_api_persistence_v1_update_proto = out.File
453 > file_temporal_server_api_persistence_v1_update_proto_goTypes = nil
454 > file_temporal_server_api_persistence_v1_update_proto_depIdxs = nil
455 }
go.temporal.io/server/chasm/lib/nexusoperation/config.go 35 covered LOC · 2 ranges

Open complete file

160 }
161
162 > func (cfg RetryPolicyConfig) build() backoff.RetryPolicy { config.go
163 > return backoff.NewExponentialRetryPolicy(cfg.InitialInterval).
164 > WithMaximumInterval(cfg.MaxInterval).
165 > WithExpirationInterval(backoff.NoInterval)
166 > }
167
168 var defaultRetryPolicyConfig = RetryPolicyConfig{
248 }
249
250 > func configProvider(dc *dynamicconfig.Collection, cfg *config.Persistence) *Config { config.go
251 > return &Config{
252 > Enabled: Enabled.Get(dc),
253 > EnableChasm: dynamicconfig.EnableChasm.Get(dc),
254 > EnableChasmNexusWorkflowOperations: EnableChasmWorkflowOperations.Get(dc),
255 > NumHistoryShards: cfg.NumHistoryShards,
256 > LongPollBuffer: LongPollBuffer.Get(dc),
257 > LongPollTimeout: LongPollTimeout.Get(dc),
258 > RequestTimeout: RequestTimeout.Get(dc),
259 > MinRequestTimeout: MinRequestTimeout.Get(dc),
260 > MaxConcurrentOperationsPerWorkflow: MaxConcurrentOperationsPerWorkflow.Get(dc),
261 > MaxServiceNameLength: MaxServiceNameLength.Get(dc),
262 > MaxOperationNameLength: MaxOperationNameLength.Get(dc),
263 > MaxOperationTokenLength: MaxOperationTokenLength.Get(dc),
264 > MaxOperationHeaderSize: MaxOperationHeaderSize.Get(dc),
265 > DisallowedOperationHeaders: DisallowedOperationHeaders.Get(dc),
266 > MaxOperationScheduleToCloseTimeout: MaxOperationScheduleToCloseTimeout.Get(dc),
267 > PayloadSizeLimit: dynamicconfig.BlobSizeLimitError.Get(dc),
268 > PayloadSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
269 > MaxUserMetadataSummarySize: dynamicconfig.MaxUserMetadataSummarySize.Get(dc),
270 > MaxUserMetadataDetailsSize: dynamicconfig.MaxUserMetadataDetailsSize.Get(dc),
271 > CallbackURLTemplate: CallbackURLTemplate.Get(dc),
272 > UseSystemCallbackURL: UseSystemCallbackURL.Get(dc),
273 > UseNewFailureWireFormat: UseNewFailureWireFormat.Get(dc),
274 > VisibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
275 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
276 > MaxReasonLength: MaxReasonLength.Get(dc),
277 > RetryPolicy: RetryPolicy.Get(dc),
278 > }
279 > }
go.temporal.io/server/common/collection/paging_iterator.go 35 covered LOC · 13 ranges

Open complete file

18 func NewPagingIterator[V any](
19 paginationFn PaginationFn[V],
20 > ) Iterator[V] { paging_iterator.go
21 > iter := &PagingIteratorImpl[V]{
22 > paginationFn: paginationFn,
23 > pageToken: nil,
24 > pageErr: nil,
25 > pageItems: nil,
26 > nextPageItemIndex: 0,
27 > }
28 > iter.getNextPage() // this will initialize the paging iterator
29 > return iter
30 > }
31
32 // NewPagingIteratorWithToken create a new paging iterator with initial token
47
48 // HasNext return whether has next item or err
49 > func (iter *PagingIteratorImpl[V]) HasNext() bool { paging_iterator.go
50 > // pagination encounters error
51 > if iter.pageErr != nil {
52 return true
53 }
54
55 // still have local cached item to return
56 > if iter.nextPageItemIndex < len(iter.pageItems) { paging_iterator.go
57 > return true paging_iterator.go
58 > }
59
60 > if len(iter.pageToken) != 0 { paging_iterator.go
61 iter.getNextPage()
62 return iter.HasNext()
63 }
64
65 > return false paging_iterator.go
66 }
67
68 // Next return next item or err
69 > func (iter *PagingIteratorImpl[V]) Next() (V, error) { paging_iterator.go
70 > if !iter.HasNext() {
71 panic("HistoryEventIterator Next() called without checking HasNext()")
72 }
73
74 > if iter.pageErr != nil { paging_iterator.go
75 err := iter.pageErr
76 iter.pageErr = nil
80
81 // we have cached events
82 > if iter.nextPageItemIndex < len(iter.pageItems) { paging_iterator.go
83 > index := iter.nextPageItemIndex
84 > iter.nextPageItemIndex++
85 > return iter.pageItems[index], nil
86 > }
87
88 panic("HistoryEventIterator Next() should return either a history event or a err")
89 }
90
91 > func (iter *PagingIteratorImpl[V]) getNextPage() { paging_iterator.go
92 > items, token, err := iter.paginationFn(iter.pageToken)
93 > if err == nil {
94 > iter.pageItems = items paging_iterator.go
95 > iter.pageToken = token
96 > iter.pageErr = nil
97 > } else { paging_iterator.go
98 iter.pageItems = nil
99 iter.pageToken = nil
100 iter.pageErr = err
101 }
102 > iter.nextPageItemIndex = 0 paging_iterator.go
103 }
go.temporal.io/server/service/frontend/nexus_completion_http_handler.go 35 covered LOC · 4 ranges

Open complete file

85 forwardingClients *cluster.FrontendHTTPClientCache,
86 httpTraceProvider commonnexus.HTTPClientTraceProvider,
87 > ) *nexusCompletionHandler { nexus_completion_http_handler.go
88 > return &nexusCompletionHandler{
89 > ClusterMetadata: clusterMetadata,
90 > NamespaceRegistry: namespaceRegistry,
91 > Logger: logger,
92 > MetricsHandler: metricsHandler,
93 > Config: serviceConfig,
94 > CallbackTokenGenerator: callbackTokenGenerator,
95 > HistoryClient: historyClient,
96 > TelemetryInterceptor: telemetryInterceptor,
97 > RequestErrorHandler: requestErrorHandler,
98 > NamespaceValidationInterceptor: namespaceValidationInterceptor,
99 > NamespaceRateLimitInterceptor: namespaceRateLimitInterceptor,
100 > NamespaceConcurrencyLimitInterceptor: namespaceConcurrencyLimitInterceptor,
101 > RateLimitInterceptor: rateLimitInterceptor,
102 > AuthInterceptor: authInterceptor,
103 > RedirectionInterceptor: redirectionInterceptor,
104 > ForwardingClients: forwardingClients,
105 > HTTPTraceProvider: httpTraceProvider,
106 > clientVersionChecker: headers.NewDefaultVersionChecker(),
107 > preProcessErrorsCounter: metricsHandler.Counter(metrics.NexusCompletionRequestPreProcessErrors.Name()),
108 > }
109 > }
110
111 > func newNexusCompletionHTTPHandler(handler *nexusCompletionHandler, logger log.Logger) *nexusCompletionHTTPHandler { nexus_completion_http_handler.go
112 > return &nexusCompletionHTTPHandler{
113 > httpHandler: nexusrpc.NewCompletionHTTPHandler(nexusrpc.CompletionHandlerOptions{
114 > Handler: handler,
115 > Logger: log.NewSlogLogger(logger),
116 > Serializer: commonnexus.PayloadSerializer,
117 > }),
118 > }
119 > }
120
121 // CompleteOperation implements nexus.CompletionHandler.
393 }
394
395 > func (h *nexusCompletionHTTPHandler) RegisterRoutes(r *mux.Router) { nexus_completion_http_handler.go
396 > r.Path("/" + commonnexus.RouteCompletionCallback.Representation()).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
397 r.Body = http.MaxBytesReader(w, r.Body, rpc.MaxNexusAPIRequestBodyBytes)
398 h.httpHandler.ServeHTTP(w, r)
399 })
400 > r.Path(commonnexus.PathCompletionCallbackNoIdentifier).HandlerFunc(func(w http.ResponseWriter, r *http.Request) { nexus_completion_http_handler.go
401 r.Body = http.MaxBytesReader(w, r.Body, rpc.MaxNexusAPIRequestBodyBytes)
402 h.httpHandler.ServeHTTP(w, r)
go.temporal.io/server/service/history/shard/task_request_tracker.go 35 covered LOC · 7 ranges

Open complete file

24 )
25
26 > func newTaskRequestTracker(registry tasks.TaskCategoryRegistry) *taskRequestTracker { task_request_tracker.go
27 > outstandingTaskKeys := make(map[tasks.Category]map[tasks.Key]struct{})
28 > for _, category := range registry.GetCategories() {
29 > outstandingTaskKeys[category] = make(map[tasks.Key]struct{})
30 > }
31 > return &taskRequestTracker{
32 > pendingTaskKeys: outstandingTaskKeys,
33 > }
34 }
35
92 func (t *taskRequestTracker) minTaskKey(
93 category tasks.Category,
94 > ) (tasks.Key, bool) { task_request_tracker.go
95 > t.Lock()
96 > defer t.Unlock()
97 >
98 > pendingTasksForCategory := t.pendingTaskKeys[category]
99 > if len(pendingTasksForCategory) == 0 {
100 > return tasks.MinimumKey, false task_request_tracker.go
101 > }
102
103 minKey := tasks.MaximumKey
115 // otherwise inflight request can fails as those requests are conditioned on
116 // the current rangeID
117 > func (t *taskRequestTracker) drain() { task_request_tracker.go
118 > t.Lock()
119 >
120 > if t.inflightRequestCount == 0 {
121 > t.Unlock()
122 > return
123 > }
124
125 waitCh := make(chan struct{})
130 }
131
132 > func (t *taskRequestTracker) clear() { task_request_tracker.go
133 > t.Lock()
134 > defer t.Unlock()
135 >
136 > for category := range t.pendingTaskKeys {
137 > t.pendingTaskKeys[category] = make(map[tasks.Key]struct{})
138 > }
139 > t.inflightRequestCount = 0
140 > t.closeWaitChannelsLocked()
141 }
142
143 > func (t *taskRequestTracker) closeWaitChannelsLocked() { task_request_tracker.go
144 > for _, waitCh := range t.waitChannels {
145 close(waitCh)
146 }
147 > t.waitChannels = nil task_request_tracker.go
148 }
go.temporal.io/server/chasm/lib/nexusoperation/operation_tasks.go 34 covered LOC · 5 ranges

Open complete file

52 }
53
54 > func newOperationInvocationTaskHandler(opts operationInvocationTaskHandlerOptions) *operationInvocationTaskHandler { operation_tasks.go
55 > return &operationInvocationTaskHandler{
56 > nexusTaskHandlerBase: opts.toBase(),
57 > callbackTokenGenerator: opts.CallbackTokenGenerator,
58 > }
59 > }
60
61 func (h *operationInvocationTaskHandler) Validate(
264 }
265
266 > func newOperationBackoffTaskHandler(opts operationTaskHandlerOptions) *operationBackoffTaskHandler { operation_tasks.go
267 > return &operationBackoffTaskHandler{
268 > config: opts.Config,
269 > metricsHandler: opts.MetricsHandler,
270 > logger: opts.Logger,
271 > }
272 > }
273
274 func (h *operationBackoffTaskHandler) Validate(
298 }
299
300 > func newOperationScheduleToStartTimeoutTaskHandler(opts operationTaskHandlerOptions) *operationScheduleToStartTimeoutTaskHandler { operation_tasks.go
301 > return &operationScheduleToStartTimeoutTaskHandler{
302 > config: opts.Config,
303 > metricsHandler: opts.MetricsHandler,
304 > logger: opts.Logger,
305 > }
306 > }
307
308 func (h *operationScheduleToStartTimeoutTaskHandler) Validate(
339 }
340
341 > func newOperationStartToCloseTimeoutTaskHandler(opts operationTaskHandlerOptions) *operationStartToCloseTimeoutTaskHandler { operation_tasks.go
342 > return &operationStartToCloseTimeoutTaskHandler{
343 > config: opts.Config,
344 > metricsHandler: opts.MetricsHandler,
345 > logger: opts.Logger,
346 > }
347 > }
348
349 func (h *operationStartToCloseTimeoutTaskHandler) Validate(
380 }
381
382 > func newOperationScheduleToCloseTimeoutTaskHandler(opts operationTaskHandlerOptions) *operationScheduleToCloseTimeoutTaskHandler { operation_tasks.go
383 > return &operationScheduleToCloseTimeoutTaskHandler{
384 > config: opts.Config,
385 > metricsHandler: opts.MetricsHandler,
386 > logger: opts.Logger,
387 > }
388 > }
389
390 func (h *operationScheduleToCloseTimeoutTaskHandler) Validate(
go.temporal.io/server/common/rpc/encryption/tls_factory.go 34 covered LOC · 24 ranges

Open complete file

66 logger log.Logger,
67 certProviderFactory CertProviderFactory,
68 > ) (TLSConfigProvider, error) { tls_factory.go
69 > if err := validateRootTLS(&encryptionSettings); err != nil {
70 return nil, err
71 }
72 > if certProviderFactory == nil { tls_factory.go
73 > certProviderFactory = NewLocalStoreCertProvider
74 > }
75 > return NewLocalStoreTlsProvider(&encryptionSettings, metricsHandler.WithTags(metrics.OperationTag(metrics.ServerTlsScope)), logger, certProviderFactory)
76 }
77
78 > func validateRootTLS(cfg *config.RootTLS) error { tls_factory.go
79 > if err := validateGroupTLS(&cfg.Internode); err != nil {
80 return err
81 }
82 > if err := validateGroupTLS(&cfg.Frontend); err != nil { tls_factory.go
83 return err
84 }
85 > return validateWorkerTLS(&cfg.SystemWorker) tls_factory.go
86 }
87
88 > func validateGroupTLS(cfg *config.GroupTLS) error { tls_factory.go
89 > if err := validateServerTLS(&cfg.Server); err != nil {
90 return err
91 }
92 > if err := validateClientTLS(&cfg.Client); err != nil { tls_factory.go
93 return err
94 }
95 > for host, hostConfig := range cfg.PerHostOverrides { tls_factory.go
96
97 if strings.TrimSpace(host) == "" {
102 }
103 }
104 > return nil tls_factory.go
105 }
106
107 > func validateWorkerTLS(cfg *config.WorkerTLS) error { tls_factory.go
108 > if cfg.CertFile != "" && cfg.CertData != "" {
109 return fmt.Errorf("cannot specify CertFile and CertData at the same time")
110 }
111 > if cfg.KeyFile != "" && cfg.KeyData != "" { tls_factory.go
112 return fmt.Errorf("cannot specify KeyFile and KeyData at the same time")
113 }
114 > return validateClientTLS(&cfg.Client) tls_factory.go
115 }
116
117 > func validateServerTLS(cfg *config.ServerTLS) error { tls_factory.go
118 > if cfg.CertFile != "" && cfg.CertData != "" {
119 return fmt.Errorf("cannot specify CertFile and CertData at the same time")
120 }
121 > if cfg.KeyFile != "" && cfg.KeyData != "" { tls_factory.go
122 return fmt.Errorf("cannot specify KeyFile and KeyData at the same time")
123 }
124 > if err := validateCAs(cfg.ClientCAData); err != nil { tls_factory.go
125 return fmt.Errorf("invalid ServerTLS.ClientCAData: %w", err)
126 }
127 > if err := validateCAs(cfg.ClientCAFiles); err != nil { tls_factory.go
128 return fmt.Errorf("invalid ServerTLS.ClientCAFiles: %w", err)
129 }
130 > if len(cfg.ClientCAFiles) > 0 && len(cfg.ClientCAData) > 0 { tls_factory.go
131 return fmt.Errorf("cannot specify ClientCAFiles and ClientCAData at the same time")
132 }
133 > return nil tls_factory.go
134 }
135
136 > func validateClientTLS(cfg *config.ClientTLS) error { tls_factory.go
137 > if err := validateCAs(cfg.RootCAData); err != nil {
138 return fmt.Errorf("invalid ClientTLS.RootCAData: %w", err)
139 }
140 > if err := validateCAs(cfg.RootCAFiles); err != nil { tls_factory.go
141 return fmt.Errorf("invalid ClientTLS.RootCAFiles: %w", err)
142 }
143 > if len(cfg.RootCAData) > 0 && len(cfg.RootCAFiles) > 0 { tls_factory.go
144 return fmt.Errorf("cannot specify RootCAFiles and RootCAData at the same time")
145 }
146 > return nil tls_factory.go
147 }
148
149 > func validateCAs(cas []string) error { tls_factory.go
150 > for _, ca := range cas {
151 if strings.TrimSpace(ca) == "" {
152 return fmt.Errorf("CA cannot be empty string")
153 }
154 }
155 > return nil tls_factory.go
156 }
go.temporal.io/server/common/rpc/interceptor/caller_info.go 34 covered LOC · 9 ranges

Open complete file

20 func NewCallerInfoInterceptor(
21 namespaceRegistry namespace.Registry,
22 > ) *CallerInfoInterceptor { caller_info.go
23 > return &CallerInfoInterceptor{
24 > namespaceRegistry: namespaceRegistry,
25 > }
26 > }
27
28 func (i *CallerInfoInterceptor) Intercept(
31 info *grpc.UnaryServerInfo,
32 handler grpc.UnaryHandler,
33 > ) (any, error) { caller_info.go
34 > ctx = PopulateCallerInfo(
35 > ctx,
36 > func() string { return string(MustGetNamespaceName(i.namespaceRegistry, req)) },
37 > func() string { return api.MethodName(info.FullMethod) },
38 )
39
40 > return handler(ctx, req) caller_info.go
41 }
42
47 nsNameGetter func() string,
48 methodGetter func() string,
49 > ) context.Context { caller_info.go
50 > callerInfo := headers.GetCallerInfo(ctx)
51 >
52 > infoUpdated := false
53 >
54 > nsName := nsNameGetter()
55 > if callerInfo.CallerName != nsName {
56 callerInfo.CallerName = nsName
57 infoUpdated = true
58 }
59
60 > _, isValidCallerType := headers.ValidCallerTypes[callerInfo.CallerType] caller_info.go
61 > if !isValidCallerType {
62 > callerInfo.CallerType = headers.CallerTypeAPI
63 > infoUpdated = true
64 > }
65
66 > if callerInfo.CallerType == headers.CallerTypeAPI || caller_info.go
67 > callerInfo.CallerType == headers.CallerTypeOperator {
68 > methodName := methodGetter()
69 > if callerInfo.CallOrigin != methodName {
70 > callerInfo.CallOrigin = methodName caller_info.go
71 > infoUpdated = true
72 > }
73 }
74
75 > if infoUpdated { caller_info.go
76 > ctx = headers.SetCallerInfo(ctx, callerInfo)
77 > }
78
79 > return ctx caller_info.go
80 }
go.temporal.io/server/service/history/queues/reader_quotas.go 34 covered LOC · 4 ranges

Open complete file

15 rateFn quotas.RateFn,
16 maxReaders int64,
17 > ) quotas.RequestRateLimiter { reader_quotas.go
18 > rateLimiters := make(map[int]quotas.RequestRateLimiter, maxReaders)
19 > readerCallerToPriority := make(map[string]int, maxReaders)
20 > for readerId := DefaultReaderId; readerId != DefaultReaderId+maxReaders; readerId++ {
21 > // use readerId as priority
22 > rateLimiters[int(readerId)] = quotas.NewRequestRateLimiterAdapter(quotas.NewDefaultOutgoingRateLimiter(rateFn))
23 > // reader will use readerId (in string type) as caller when using the rate limiter
24 > readerCallerToPriority[newReaderRequest(readerId).Caller] = int(readerId)
25 > }
26 > lowestPriority := int(DefaultReaderId + maxReaders - 1)
27 >
28 > return quotas.NewPriorityRateLimiter(
29 > func(req quotas.Request) int {
30 > if priority, ok := readerCallerToPriority[req.Caller]; ok { reader_quotas.go
31 > return priority
32 > }
33 return lowestPriority
34 },
41 hostReaderRateLimiter quotas.RequestRateLimiter,
42 maxReaders int64,
43 > ) quotas.RequestRateLimiter { reader_quotas.go
44 > return quotas.NewMultiRequestRateLimiter(
45 > NewReaderPriorityRateLimiter(
46 > func() float64 { return float64(shardMaxPollRPS()) },
47 maxReaders,
48 ),
53 func newReaderRequest(
54 readerID int64,
55 > ) quotas.Request { reader_quotas.go
56 > // The priority is only based on readerID (caller),
57 > // api, caller type, caller segment, and call initiation (origin)
58 > // are the same for all the readers, and not related to
59 > // priority so leaving those fields empty.
60 > return quotas.NewRequest(
61 > "",
62 > readerRequestToken,
63 > strconv.FormatInt(readerID, 10),
64 > "",
65 > 0,
66 > "",
67 > )
68 > }
go.temporal.io/server/service/history/queues/speculative_workflow_task_timeout_queue.go 34 covered LOC · 5 ranges

Open complete file

40 tracer trace.Tracer,
41 logger log.SnTaggedLogger,
42 > ) *SpeculativeWorkflowTaskTimeoutQueue { speculative_workflow_task_timeout_queue.go
43 >
44 > timeoutQueue := newMemoryScheduledQueue(
45 > scheduler,
46 > timeSource,
47 > logger,
48 > metricsHandler,
49 > )
50 >
51 > return &SpeculativeWorkflowTaskTimeoutQueue{
52 > timeoutQueue: timeoutQueue,
53 > executor: executor,
54 > priorityAssigner: priorityAssigner,
55 > namespaceRegistry: namespaceRegistry,
56 > clusterMetadata: clusterMetadata,
57 > timeSource: timeSource,
58 > chasmRegistry: chasmRegistry,
59 > metricsHandler: metricsHandler,
60 > tracer: tracer,
61 > logger: logger,
62 > }
63 > }
64
65 > func (q SpeculativeWorkflowTaskTimeoutQueue) Start() { speculative_workflow_task_timeout_queue.go
66 > q.timeoutQueue.Start()
67 > }
68
69 > func (q SpeculativeWorkflowTaskTimeoutQueue) Stop() { speculative_workflow_task_timeout_queue.go
70 > q.timeoutQueue.Stop()
71 > }
72
73 > func (q SpeculativeWorkflowTaskTimeoutQueue) Category() tasks.Category { speculative_workflow_task_timeout_queue.go
74 > return tasks.CategoryMemoryTimer
75 > }
76
77 > func (q SpeculativeWorkflowTaskTimeoutQueue) NotifyNewTasks(ts []tasks.Task) { speculative_workflow_task_timeout_queue.go
78 > for _, task := range ts {
79 > if wttt, ok := task.(*tasks.WorkflowTaskTimeoutTask); ok {
80 executable := newSpeculativeWorkflowTaskTimeoutExecutable(NewExecutable(
81 0,
go.temporal.io/server/chasm/lib/workflow/library.go 33 covered LOC · 7 ranges

Open complete file

24 saMapperProvider searchattribute.MapperProvider,
25 saValidator *searchattribute.Validator,
26 > ) *library { library.go
27 > return &library{
28 > registry: registry,
29 > config: config,
30 > saMapperProvider: saMapperProvider,
31 > saValidator: saValidator,
32 > workflowServiceNexusHandler: &workflowServiceNexusHandler{
33 > config: config,
34 > namespaceRegistry: namespaceRegistry,
35 > },
36 > }
37 > }
38
39 // NewLibrary creates a new CHASM library for the workflow package.
43 }
44
45 > func (l *library) Name() string { library.go
46 > return chasm.WorkflowLibraryName
47 > }
48
49 type workflowContext struct {
63 }
64
65 > func (l *library) Components() []*chasm.RegistrableComponent { library.go
66 > return []*chasm.RegistrableComponent{
67 > chasm.NewRegistrableComponent[*Workflow](chasm.WorkflowComponentName, chasm.WithContextValues(map[any]any{
68 > ctxKeyWorkflowContext: &workflowContext{registry: l.registry},
69 > })),
70 > chasm.NewRegistrableComponent[*WorkflowUpdate]("update"),
71 > }
72 > }
73
74 // SetEventRegistryOnContext injects the event registry into a CHASM context. This is primarily
78 }
79
80 > func (l *library) NexusServices() []*nexus.Service { library.go
81 > if l.workflowServiceNexusHandler == nil {
82 return nil
83 }
84 > return []*nexus.Service{ library.go
85 > mustNewWorkflowServiceNexusHandler(l.workflowServiceNexusHandler),
86 > }
87 }
88
89 > func (l *library) NexusServiceProcessors() []*chasm.NexusServiceProcessor { library.go
90 > if l.workflowServiceNexusHandler == nil {
91 return nil
92 }
93 > return []*chasm.NexusServiceProcessor{ library.go
94 > NewWorkflowServiceNexusServiceProcessor(l.config, l.saMapperProvider, l.saValidator),
95 > }
96 }
go.temporal.io/server/common/membership/ringpop/hostinfo.go 33 covered LOC · 10 ranges

Open complete file

23
24 // newHostInfo creates a new *hostInfo instance
25 > func newHostInfo(addr string, labels map[string]string) *hostInfo { hostinfo.go
26 > return &hostInfo{
27 > addr: addr,
28 > labels: labels,
29 > labelsChecksum: checksumLabels(labels),
30 > }
31 > }
32
33 // GetAddress returns the ip:port address
34 > func (hi *hostInfo) GetAddress() string { hostinfo.go
35 > return hi.addr
36 > }
37
38 // Identity implements ringpop's Membership interface
39 > func (hi *hostInfo) Identity() string { hostinfo.go
40 > // For now, we just use the address as the identity.
41 > return hi.addr
42 > }
43
44 // Label implements ringpop's Membership interface
49
50 // summary returns a shorthand summary string suitable for logging.
51 > func (hi *hostInfo) summary() string { hostinfo.go
52 > var s strings.Builder
53 > s.WriteString(hi.GetAddress())
54 > for k, v := range hi.labels {
55 > switch k {
56 > case roleKey, portKey: hostinfo.go
57 // skip these, they can be determined from context
58 > default: hostinfo.go
59 > s.WriteString(fmt.Sprintf("[%s=%s]", k, v))
60 }
61 }
62 > return s.String() hostinfo.go
63 }
64
65 // checksumLabels returns a checksum of a labels map
66 > func checksumLabels(labels map[string]string) uint64 { hostinfo.go
67 > var c uint64
68 > for k, v := range labels {
69 > kfp := farm.Fingerprint64([]byte(k)) hostinfo.go
70 > vfp := farm.Fingerprint64([]byte(v))
71 > // use xor to combine different labels so that it comes out the same with any iteration
72 > // order, without needing to sort.
73 > c ^= kfp + bits.RotateLeft64(vfp, 3)
74 > }
75 > return c hostinfo.go
76 }
go.temporal.io/server/common/quotas/calculator/logged_calculator.go 33 covered LOC · 7 ranges

Open complete file

38 calculator Calculator,
39 logger log.Logger,
40 > ) *LoggedCalculator { logged_calculator.go
41 > return &LoggedCalculator{
42 > quotaLogger: newQuotaLogger(logger),
43 > calculator: calculator,
44 > }
45 > }
46
47 > func (c *LoggedCalculator) GetQuota() float64 { logged_calculator.go
48 > quota := c.calculator.GetQuota()
49 > c.quotaLogger.updateQuota(quota)
50 > return quota
51 > }
52
53 func NewLoggedNamespaceCalculator(
54 calculator NamespaceCalculator,
55 logger log.Logger,
56 > ) *LoggedNamespaceCalculator { logged_calculator.go
57 > return &LoggedNamespaceCalculator{
58 > calculator: calculator,
59 > logger: logger,
60 > quotaLoggers: make(map[string]*quotaLogger[float64]),
61 > }
62 > }
63
64 func (c *LoggedNamespaceCalculator) GetQuota(namespace string) float64 {
85 func newQuotaLogger(
86 logger log.Logger,
87 > ) *quotaLogger[float64] { logged_calculator.go
88 > return &quotaLogger[float64]{
89 > logger: logger,
90 > }
91 > }
92
93 > func (l *quotaLogger[T]) updateQuota(newQuota T) { logged_calculator.go
94 > currentQuota := l.currentValue.Swap(newQuota)
95 >
96 > if currentQuota != nil && newQuota == currentQuota.(T) {
97 > return logged_calculator.go
98 > }
99
100 > l.logger.Info("Quota changed", logged_calculator.go
101 > tag.Any("current-quota", currentQuota),
102 > tag.Any("new-quota", newQuota),
103 > )
104 }
go.temporal.io/server/common/quotas/multi_request_rate_limiter_impl.go 33 covered LOC · 12 ranges

Open complete file

17 func NewMultiRequestRateLimiter(
18 requestRateLimiters ...RequestRateLimiter,
19 > ) *MultiRequestRateLimiterImpl { multi_request_rate_limiter_impl.go
20 > if len(requestRateLimiters) == 0 {
21 panic("expect at least one rate limiter")
22 }
23 > return &MultiRequestRateLimiterImpl{ multi_request_rate_limiter_impl.go
24 > requestRateLimiters: requestRateLimiters,
25 > }
26 }
27
28 > func (rl *MultiRequestRateLimiterImpl) Allow(now time.Time, request Request) bool { multi_request_rate_limiter_impl.go
29 > length := len(rl.requestRateLimiters)
30 > reservations := make([]Reservation, 0, length)
31 >
32 > for _, requestRateLimiter := range rl.requestRateLimiters {
33 > reservation := requestRateLimiter.Reserve(now, request)
34 > if !reservation.OK() || reservation.DelayFrom(now) > 0 {
35 if reservation.OK() {
36 reservation.CancelAt(now)
43 return false
44 }
45 > reservations = append(reservations, reservation) multi_request_rate_limiter_impl.go
46 }
47
49 }
50
51 > func (rl *MultiRequestRateLimiterImpl) Reserve(now time.Time, request Request) Reservation { multi_request_rate_limiter_impl.go
52 > length := len(rl.requestRateLimiters)
53 > reservations := make([]Reservation, 0, length)
54 >
55 > for _, requestRateLimiter := range rl.requestRateLimiters {
56 > reservation := requestRateLimiter.Reserve(now, request)
57 > if !reservation.OK() {
58 // cancel all existing reservation
59 for _, reservation := range reservations {
62 return NewMultiReservation(false, nil)
63 }
64 > reservations = append(reservations, reservation) multi_request_rate_limiter_impl.go
65 }
66
67 > return NewMultiReservation(true, reservations) multi_request_rate_limiter_impl.go
68 }
69
70 > func (rl *MultiRequestRateLimiterImpl) Wait(ctx context.Context, request Request) error { multi_request_rate_limiter_impl.go
71 > select {
72 case <-ctx.Done():
73 return ctx.Err()
75 }
76
77 > now := time.Now().UTC() multi_request_rate_limiter_impl.go
78 > reservation := rl.Reserve(now, request)
79 > if !reservation.OK() {
80 return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", request.Token)
81 }
82
83 > delay := reservation.DelayFrom(now) multi_request_rate_limiter_impl.go
84 > if delay == 0 {
85 > return nil
86 > }
87 waitLimit := InfDuration
88 if deadline, ok := ctx.Deadline(); ok {
go.temporal.io/server/common/rpc/grpc.go 33 covered LOC · 5 ranges

Open complete file

54 metricsHandler metrics.Handler,
55 opts ...grpc.DialOption,
56 > ) (*grpc.ClientConn, error) { grpc.go
57 > var grpcSecureOpt grpc.DialOption
58 > if tlsConfig == nil {
59 > grpcSecureOpt = grpc.WithTransportCredentials(insecure.NewCredentials()) grpc.go
60 > } else { grpc.go
61 grpcSecureOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
62 }
67 // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
68 // Default MaxDelay is 120 seconds which is too high.
69 > var cp = grpc.ConnectParams{ grpc.go
70 > Backoff: backoff.DefaultConfig,
71 > MinConnectTimeout: minConnectTimeout,
72 > }
73 > cp.Backoff.MaxDelay = MaxBackoffDelay
74 >
75 > dtrace := newDialTracer(hostName, metricsHandler, logger)
76 >
77 > contextDialer := func(ctx context.Context, s string) (net.Conn, error) {
78 // Keep the existing gRPC behavior by using OS defaults for TCP keepalive settings.
79 // We are on Go 1.23+ and can use KeepAliveConfig directly instead of the old KeepAlive/Control hacks.
91 }
92
93 > dialOptions := []grpc.DialOption{ grpc.go
94 > grpcSecureOpt,
95 > grpc.WithContextDialer(contextDialer),
96 > grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxInternodeRecvPayloadSize)),
97 > grpc.WithChainUnaryInterceptor(
98 > headersInterceptor,
99 > metrics.NewClientMetricsTrailerPropagatorInterceptor(logger),
100 > errorInterceptor,
101 > ),
102 > grpc.WithChainStreamInterceptor(
103 > interceptor.StreamErrorInterceptor,
104 > ),
105 > grpc.WithDefaultServiceConfig(DefaultServiceConfig),
106 > grpc.WithDisableServiceConfig(),
107 > grpc.WithConnectParams(cp),
108 > }
109 > dialOptions = append(dialOptions, opts...)
110 >
111 > return grpc.NewClient(hostName, dialOptions...)
112 }
113
go.temporal.io/server/common/testing/freeport/freeport.go 33 covered LOC · 7 ranges

Open complete file

22 // in this regard; on that platform, `SO_REUSEADDR` has a different meaning and
23 // should not be set (setting it may have unpredictable consequences).
24 > func MustGetFreePort() int { freeport.go
25 > port, err := getFreePort("127.0.0.1")
26 > if err != nil {
27 // try ipv6
28 port, err = getFreePort("[::1]")
31 }
32 }
33 > return port freeport.go
34 }
35
36 > func getFreePort(host string) (int, error) { freeport.go
37 > l, err := net.Listen("tcp", host+":0")
38 > if err != nil {
39 return 0, fmt.Errorf("failed to assign a free port: %v", err)
40 }
41 > defer l.Close() freeport.go
42 > port := l.Addr().(*net.TCPAddr).Port
43 >
44 > // On Linux and some BSD variants, ephemeral ports are randomized, and may
45 > // consequently repeat within a short time frame after the listening end
46 > // has been closed. To avoid this, we make a connection to the port, then
47 > // close that connection from the server's side (this is very important),
48 > // which puts the connection in TIME_WAIT state for some time (by default,
49 > // 60s on Linux). While it remains in that state, the OS will not reallocate
50 > // that port number for bind(:0) syscalls, yet we are not prevented from
51 > // explicitly binding to it (thanks to SO_REUSEADDR).
52 > //
53 > // On macOS and Windows, the above technique is not necessary, as the OS
54 > // allocates ephemeral ports sequentially, meaning a port number will only
55 > // be reused after the entire range has been exhausted. Quite the opposite,
56 > // given that these OSes use a significantly smaller range for ephemeral
57 > // ports, making an extra connection just to reserve a port might actually
58 > // be harmful (by hastening ephemeral port exhaustion).
59 > if runtime.GOOS != "darwin" && runtime.GOOS != "windows" {
60 > r, err := net.DialTCP("tcp", nil, l.Addr().(*net.TCPAddr))
61 > if err != nil {
62 return 0, fmt.Errorf("failed to assign a free port: %v", err)
63 }
64 > c, err := l.Accept() freeport.go
65 > if err != nil {
66 return 0, fmt.Errorf("failed to assign a free port: %v", err)
67 }
68 // Closing the socket from the server side
69 > _ = c.Close() freeport.go
70 > defer r.Close()
71 }
72
73 > return port, nil freeport.go
74 }
go.temporal.io/server/service/history/history_engine_factory.go 32 covered LOC · 1 range

Open complete file

65 func (f *historyEngineFactory) CreateEngine(
66 shard historyi.ShardContext,
67 > ) historyi.Engine { history_engine_factory.go
68 > return NewEngineWithShardContext(
69 > shard,
70 > f.ClientBean,
71 > f.MatchingClient,
72 > f.SdkClientFactory,
73 > f.EventNotifier,
74 > f.Config,
75 > f.VersionMembershipCache,
76 > f.WorkerDeploymentClient,
77 > f.RoutingInfoCache,
78 > f.RawMatchingClient,
79 > f.WorkflowCache,
80 > f.ReplicationProgressCache,
81 > f.Serializer,
82 > f.QueueFactories,
83 > f.ReplicationTaskFetcherFactory,
84 > f.ReplicationTaskExecutorProvider,
85 > api.NewWorkflowConsistencyChecker(shard, f.WorkflowCache),
86 > f.TracerProvider,
87 > f.PersistenceVisibilityMgr,
88 > f.EventBlobCache,
89 > f.TaskCategoryRegistry,
90 > f.ReplicationDLQWriter,
91 > f.CommandHandlerRegistry,
92 > f.ChasmWorkflowRegistry,
93 > f.OutboundQueueCBPool,
94 > f.PersistenceRateLimiter,
95 > f.TestHooks,
96 > f.ChasmEngine,
97 > )
98 > }
go.temporal.io/server/service/worker/parentclosepolicy/processor.go 32 covered LOC · 3 ranges

Open complete file

57
58 // New returns a new instance as daemon
59 > func New(params *BootstrapParams) *Processor { processor.go
60 > return &Processor{
61 > sdkClientFactory: params.SdkClientFactory,
62 > metricsHandler: params.MetricsHandler.WithTags(metrics.OperationTag(metrics.ParentClosePolicyProcessorScope)),
63 > cfg: params.Config,
64 > logger: log.With(params.Logger, tag.ComponentBatcher),
65 > clientBean: params.ClientBean,
66 > currentCluster: params.CurrentCluster,
67 > hostInfo: params.HostInfo,
68 > }
69 > }
70
71 // Start starts the scanner
72 > func (s *Processor) Start() error { processor.go
73 > svcClient := s.sdkClientFactory.GetSystemClient()
74 > processorWorker := s.sdkClientFactory.NewWorker(svcClient, processorTaskQueueName, getWorkerOptions(s))
75 > processorWorker.RegisterWorkflowWithOptions(ProcessorWorkflow, workflow.RegisterOptions{Name: processorWFTypeName})
76 > processorWorker.RegisterActivityWithOptions(ProcessorActivity, activity.RegisterOptions{Name: processorActivityName})
77 >
78 > return processorWorker.Start()
79 > }
80
81 > func getWorkerOptions(p *Processor) worker.Options { processor.go
82 > ctx := context.WithValue(context.Background(), processorContextKey, p)
83 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
84 >
85 > return worker.Options{
86 > MaxConcurrentActivityExecutionSize: p.cfg.MaxConcurrentActivityExecutionSize(),
87 > MaxConcurrentWorkflowTaskExecutionSize: p.cfg.MaxConcurrentWorkflowTaskExecutionSize(),
88 > MaxConcurrentActivityTaskPollers: p.cfg.MaxConcurrentActivityTaskPollers(),
89 > MaxConcurrentWorkflowTaskPollers: p.cfg.MaxConcurrentWorkflowTaskPollers(),
90 > BackgroundActivityContext: ctx,
91 > Identity: "temporal-system@" + p.hostInfo.Identity(),
92 > }
93 > }
go.temporal.io/server/chasm/lib/callback/library.go 31 covered LOC · 5 ranges

Open complete file

24 InvocationTaskHandler *invocationTaskHandler,
25 BackoffTaskHandler *backoffTaskHandler,
26 > ) *Library { library.go
27 > return &Library{
28 > InvocationTaskHandler: InvocationTaskHandler,
29 > BackoffTaskHandler: BackoffTaskHandler,
30 > }
31 > }
32
33 > func (l *Library) Name() string { library.go
34 > return chasm.CallbackLibraryName
35 > }
36
37 > func (l *Library) Components() []*chasm.RegistrableComponent { library.go
38 > return []*chasm.RegistrableComponent{
39 > chasm.NewRegistrableComponent[*Callback](
40 > chasm.CallbackComponentName,
41 > chasm.WithDetached(),
42 > ),
43 > }
44 > }
45
46 > func (l *Library) Tasks() []*chasm.RegistrableTask { library.go
47 > return []*chasm.RegistrableTask{
48 > chasm.NewRegistrableSideEffectTask(
49 > "invoke",
50 > l.InvocationTaskHandler,
51 > ),
52 > chasm.NewRegistrablePureTask(
53 > "backoff",
54 > l.BackoffTaskHandler,
55 > ),
56 > }
57 > }
58
59 > func (l *Library) RegisterServices(server *grpc.Server) { library.go
60 > }
go.temporal.io/server/common/dynamicconfig/deepcopy.go 31 covered LOC · 6 ranges

Open complete file

9 // deepCopyForMapstructure does a simple deep copy of T. Fancy cases (anything other than plain old data)
10 // is not handled and will panic.
11 > func deepCopyForMapstructure[T any](t T) T { deepcopy.go
12 > // nolint:revive // this will be triggered from a static initializer before it can be triggered from production code
13 > return deepCopyValue(reflect.ValueOf(t)).Interface().(T)
14 > }
15
16 > func deepCopyValue(v reflect.Value) reflect.Value { deepcopy.go
17 > switch v.Kind() {
18 case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
19 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
20 > reflect.Uintptr, reflect.Float32, reflect.Float64, reflect.String: deepcopy.go
21 > nv := reflect.New(v.Type()).Elem()
22 > nv.Set(v)
23 > return nv
24 case reflect.Array:
25 nv := reflect.New(v.Type()).Elem()
42 }
43 return deepCopyValue(v.Elem()).Addr()
44 > case reflect.Slice: deepcopy.go
45 > if v.IsNil() {
46 > return v
47 > }
48 nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
49 for i := range v.Len() {
51 }
52 return nv
53 > case reflect.Struct: deepcopy.go
54 > // Special case for time.Time: it has unexported fields so we can't copy it field by
55 > // field, but we can copy zero values (which is all we need for default values).
56 > if v.Type() == reflect.TypeFor[time.Time]() {
57 > if v.Interface().(time.Time).IsZero() {
58 > return reflect.ValueOf(time.Time{})
59 > }
60 // nolint:forbidigo // this will be triggered from a static initializer before it can be triggered from production code
61 panic(fmt.Sprintf("Can't deep copy non-zero time.Time: %v", v.Interface()))
62 }
63 > nv := reflect.New(v.Type()).Elem() deepcopy.go
64 > for i := range v.Type().NumField() {
65 > nv.Field(i).Set(deepCopyValue(v.Field(i)))
66 > }
67 > return nv
68 > case reflect.Interface, reflect.Func, reflect.Chan:
69 > // only nil values of any other reference types allowed!
70 > if v.IsNil() {
71 > return v
72 > }
73 fallthrough
74 default:
go.temporal.io/server/common/persistence/client/health_request_rate_limiter.go 31 covered LOC · 5 ranges

Open complete file

50 metricsHandler metrics.Handler,
51 logger log.Logger,
52 > ) *HealthRequestRateLimiterImpl { health_request_rate_limiter.go
53 > rateBurst := quotas.NewDefaultRateBurst(rateFn, quotas.BurstRatioFn(burstRatio))
54 > limiter := &HealthRequestRateLimiterImpl{
55 > enabled: atomic.Bool{},
56 > rateLimiter: quotas.NewRateLimiter(rateBurst.Rate(), rateBurst.Burst()),
57 > healthSignals: healthSignals,
58 > rateBurst: rateBurst,
59 > params: params,
60 > refreshTimer: time.NewTicker(DefaultRefreshInterval),
61 > metricsHandler: metricsHandler,
62 > logger: logger,
63 > }
64 > curRateMultiplier := new(float64)
65 > *curRateMultiplier = DefaultInitialRateMultiplier
66 > limiter.curRateMultiplier.Store(curRateMultiplier)
67 > limiter.refreshDynamicParams()
68 > return limiter
69 > }
70
71 func (rl *HealthRequestRateLimiterImpl) Allow(now time.Time, request quotas.Request) bool {
77 }
78
79 > func (rl *HealthRequestRateLimiterImpl) Reserve(now time.Time, request quotas.Request) quotas.Reservation { health_request_rate_limiter.go
80 > rl.maybeRefresh()
81 > if !rl.enabled.Load() {
82 > return quotas.NoopReservation
83 > }
84 return rl.rateLimiter.ReserveN(now, request.Token)
85 }
93 }
94
95 > func (rl *HealthRequestRateLimiterImpl) maybeRefresh() { health_request_rate_limiter.go
96 > select {
97 case <-rl.refreshTimer.C:
98 rl.refreshDynamicParams()
139 }
140
141 > func (rl *HealthRequestRateLimiterImpl) refreshDynamicParams() { health_request_rate_limiter.go
142 > options := rl.params()
143 > rl.enabled.Store(options.Enabled)
144 > rl.curOptions.Store(&options)
145 > }
146
147 func (rl *HealthRequestRateLimiterImpl) updateRefreshTimer() {
go.temporal.io/server/common/persistence/serialization/codec.go 31 covered LOC · 13 ranges

Open complete file

26 // encodingTypeFromEnv returns an EncodingType based on the environment variable `TEMPORAL_TEST_DATA_ENCODING`.
27 // It defaults to "ENCODING_TYPE_PROTO3" codec if the environment variable is not set.
28 > func encodingTypeFromEnv() enumspb.EncodingType { codec.go
29 > codecType := os.Getenv(SerializerDataEncodingEnvVar)
30 > switch strings.ToLower(codecType) {
31 > case "", "proto3": codec.go
32 > return enumspb.ENCODING_TYPE_PROTO3
33 case "json":
34 return enumspb.ENCODING_TYPE_JSON
65 encoding enumspb.EncodingType,
66 options ...EncodeOption,
67 > ) (*commonpb.DataBlob, error) { codec.go
68 > opts := encodeOptions{}
69 > for _, option := range options {
70 option(&opts)
71 }
72
73 > if m == nil { codec.go
74 return &commonpb.DataBlob{
75 Data: nil,
78 }
79
80 > switch encoding { codec.go
81 > case enumspb.ENCODING_TYPE_JSON: codec.go
82 > blob, err := codec.NewJSONPBEncoder().Encode(m)
83 > if err != nil {
84 return nil, err
85 }
86 > return &commonpb.DataBlob{ codec.go
87 > Data: blob,
88 > EncodingType: enumspb.ENCODING_TYPE_JSON,
89 > }, nil
90 > case enumspb.ENCODING_TYPE_PROTO3: codec.go
91 > data, err := proto.MarshalOptions{Deterministic: opts.deterministic}.Marshal(m)
92 > if err != nil {
93 return nil, NewSerializationError(enumspb.ENCODING_TYPE_PROTO3, err)
94 }
95 > return &commonpb.DataBlob{ codec.go
96 > EncodingType: enumspb.ENCODING_TYPE_PROTO3,
97 > Data: data,
98 > }, nil
99 default:
100 return nil, NewUnknownEncodingTypeError(encoding.String(), enumspb.ENCODING_TYPE_JSON, enumspb.ENCODING_TYPE_PROTO3)
102 }
103
104 > func Decode(data *commonpb.DataBlob, result proto.Message) error { codec.go
105 > if data == nil {
106 return NewDeserializationError(enumspb.ENCODING_TYPE_UNSPECIFIED, errors.New("cannot decode nil"))
107 }
108
109 > switch data.EncodingType { codec.go
110 case enumspb.ENCODING_TYPE_JSON:
111 return codec.NewJSONPBEncoder().Decode(data.Data, result)
112 > case enumspb.ENCODING_TYPE_PROTO3: codec.go
113 > err := proto.Unmarshal(data.Data, result)
114 > if err != nil {
115 return NewDeserializationError(enumspb.ENCODING_TYPE_PROTO3, err)
116 }
117 > return nil codec.go
118 default:
119 return NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_JSON, enumspb.ENCODING_TYPE_PROTO3)
go.temporal.io/server/service/history/shard/task_key_generator.go 31 covered LOC · 6 ranges

Open complete file

39 logger log.Logger,
40 renewRangeIDFn renewRangeIDFn,
41 > ) *taskKeyGenerator { task_key_generator.go
42 > return &taskKeyGenerator{
43 > nextTaskID: taskIDUninitialized,
44 > exclusiveMaxTaskID: taskIDUninitialized,
45 > rangeSizeBits: rangeSizeBits,
46 > timeSource: timeSource,
47 > logger: logger,
48 > renewRangeIDFn: renewRangeIDFn,
49 > }
50 > }
51
52 func (a *taskKeyGenerator) setTaskKeys(
114 func (a *taskKeyGenerator) peekTaskKey(
115 category tasks.Category,
116 > ) tasks.Key { task_key_generator.go
117 > switch category.Type() {
118 > case tasks.CategoryTypeImmediate: task_key_generator.go
119 > return tasks.NewImmediateKey(a.nextTaskID)
120 > case tasks.CategoryTypeScheduled: task_key_generator.go
121 > return tasks.NewKey(
122 > a.taskMinScheduledTime,
123 > a.nextTaskID,
124 > )
125 default:
126 panic(fmt.Sprintf("Unknown category type: %v", category.Type()))
149 }
150
151 > func (a *taskKeyGenerator) setRangeID(rangeID int64) { task_key_generator.go
152 > a.nextTaskID = rangeID << a.rangeSizeBits
153 > a.exclusiveMaxTaskID = (rangeID + 1) << a.rangeSizeBits
154 >
155 > a.logger.Info("Task key range updated",
156 > tag.Number(a.nextTaskID),
157 > tag.NextNumber(a.exclusiveMaxTaskID),
158 > )
159 > }
160
161 func (a *taskKeyGenerator) setTaskMinScheduledTime(
162 taskMinScheduledTime time.Time,
164 > a.taskMinScheduledTime = util.MaxTime(a.taskMinScheduledTime, taskMinScheduledTime)
165 > }
166
167 func (a *taskKeyGenerator) generateTaskID() (int64, error) {
go.temporal.io/server/common/headers/headers.go 30 covered LOC · 12 ranges

Open complete file

45 // GetValues returns header values for passed header names.
46 // It always returns slice of the same size as number of passed header names.
47 > func GetValues(ctx context.Context, headerNames ...string) []string { headers.go
48 > headerValues := make([]string, len(headerNames))
49 >
50 > for i, headerName := range headerNames {
51 > if values := metadata.ValueFromIncomingContext(ctx, headerName); len(values) > 0 {
52 > headerValues[i] = values[0] headers.go
53 > }
54 }
55
56 > return headerValues headers.go
57 }
58
88 }
89
90 > func NewGRPCHeaderGetter(ctx context.Context) GRPCHeaderGetter { headers.go
91 > return GRPCHeaderGetter{ctx: ctx}
92 > }
93
94 // Get a single value from the underlying gRPC metadata.
95 // Returns an empty string if the metadata key is unset.
96 > func (h GRPCHeaderGetter) Get(key string) string { headers.go
97 > if values := metadata.ValueFromIncomingContext(h.ctx, key); len(values) > 0 {
98 return values[0]
99 }
100 > return "" headers.go
101 }
102
125 // StripPrincipal removes principal headers from incoming metadata to prevent
126 // external callers from spoofing principal identity.
127 > func StripPrincipal(ctx context.Context) context.Context { headers.go
128 > mdIncoming, ok := metadata.FromIncomingContext(ctx)
129 > if !ok {
130 return ctx
131 }
132 > mdIncoming.Delete(PrincipalTypeHeaderName) headers.go
133 > mdIncoming.Delete(PrincipalNameHeaderName)
134 > return metadata.NewIncomingContext(ctx, mdIncoming)
135 }
136
154 // setIncomingMD sets the key-value pairs in the incoming metadata.
155 // Empty values are ignored.
156 > func setIncomingMD(ctx context.Context, kv map[string]string) context.Context { headers.go
157 > mdIncoming, ok := metadata.FromIncomingContext(ctx)
158 > if !ok {
159 > mdIncoming = metadata.MD{} headers.go
160 > }
161 > for k, v := range kv { headers.go
162 > if v != "" {
163 > mdIncoming.Set(k, v)
164 > }
165 }
166 > return metadata.NewIncomingContext(ctx, mdIncoming) headers.go
167 }
go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/execution_maps.go 30 covered LOC · 5 ranges

Open complete file

53 )
54
55 > func stringMap(a []string, f func(string) string) []string { execution_maps.go
56 > b := make([]string, len(a))
57 > for i, v := range a {
58 > b[i] = f(v)
59 > }
60 > return b
61 }
62
63 > func makeDeleteMapQry(tableName string) string { execution_maps.go
64 > return fmt.Sprintf(deleteMapQryTemplate, tableName)
65 > }
66
67 > func makeSetKeyInMapQry(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
68 > return fmt.Sprintf(setKeyInMapQryTemplate,
69 > tableName,
70 > strings.Join(nonPrimaryKeyColumns, ","),
71 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
72 > return ":" + x
73 > }), ","),
74 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
75 > return x + "=VALUES(" + x + ")"
76 > }), ","),
77 mapKeyName)
78 }
79
80 > func makeDeleteKeyInMapQry(tableName string, mapKeyName string) string { execution_maps.go
81 > return fmt.Sprintf(deleteKeyInMapQryTemplate,
82 > tableName,
83 > mapKeyName)
84 > }
85
86 > func makeGetMapQryTemplate(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
87 > return fmt.Sprintf(getMapQryTemplate,
88 > tableName,
89 > mapKeyName,
90 > strings.Join(nonPrimaryKeyColumns, ","))
91 > }
92
93 var (
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/execution_maps.go 30 covered LOC · 6 ranges

Open complete file

86 )
87
88 > func stringMap(a []string, f func(string) string) []string { execution_maps.go
89 > b := make([]string, len(a))
90 > for i, v := range a {
91 > b[i] = f(v)
92 > }
93 > return b
94 }
95
96 > func makeDeleteMapQry(tableName string) string { execution_maps.go
97 > return fmt.Sprintf(deleteMapQueryTemplate, tableName)
98 > }
99
100 > func makeSetKeyInMapQry(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
101 > return fmt.Sprintf(setKeyInMapQueryTemplate,
102 > tableName,
103 > strings.Join(nonPrimaryKeyColumns, ","),
104 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
105 > return ":" + x
106 > }), ","),
107 mapKeyName,
108 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string { execution_maps.go
109 > return "excluded." + x
110 > }), ","))
111 }
112
113 > func makeDeleteKeyInMapQry(tableName string, mapKeyName string) string { execution_maps.go
114 > return fmt.Sprintf(deleteKeyInMapQueryTemplate,
115 > tableName,
116 > mapKeyName)
117 > }
118
119 > func makeGetMapQryTemplate(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
120 > return fmt.Sprintf(getMapQueryTemplate,
121 > tableName,
122 > mapKeyName,
123 > strings.Join(nonPrimaryKeyColumns, ","))
124 > }
125
126 var (
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/execution_maps.go 30 covered LOC · 5 ranges

Open complete file

52 )
53
54 > func stringMap(a []string, f func(string) string) []string { execution_maps.go
55 > b := make([]string, len(a))
56 > for i, v := range a {
57 > b[i] = f(v)
58 > }
59 > return b
60 }
61
62 > func makeDeleteMapQry(tableName string) string { execution_maps.go
63 > return fmt.Sprintf(deleteMapQryTemplate, tableName)
64 > }
65
66 > func makeSetKeyInMapQry(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
67 > return fmt.Sprintf(setKeyInMapQryTemplate,
68 > tableName,
69 > strings.Join(nonPrimaryKeyColumns, ","),
70 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
71 > return ":" + x
72 > }), ","),
73 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
74 > return x + "=" + x
75 > }), ","),
76 mapKeyName)
77 }
78
79 > func makeDeleteKeyInMapQry(tableName string, mapKeyName string) string { execution_maps.go
80 > return fmt.Sprintf(deleteKeyInMapQryTemplate,
81 > tableName,
82 > mapKeyName)
83 > }
84
85 > func makeGetMapQryTemplate(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
86 > return fmt.Sprintf(getMapQryTemplate,
87 > tableName,
88 > mapKeyName,
89 > strings.Join(nonPrimaryKeyColumns, ","))
90 > }
91
92 var (
go.temporal.io/server/components/nexusoperations/executors.go 30 covered LOC · 7 ranges

Open complete file

74 registry *hsm.Registry,
75 options TaskExecutorOptions,
76 > ) error { executors.go
77 > exec := taskExecutor{options}
78 > if err := hsm.RegisterImmediateExecutor(
79 > registry,
80 > exec.executeInvocationTask,
81 > ); err != nil {
82 return err
83 }
84 > if err := hsm.RegisterTimerExecutor( executors.go
85 > registry,
86 > exec.executeBackoffTask,
87 > ); err != nil {
88 return err
89 }
90 > if err := hsm.RegisterTimerExecutor( executors.go
91 > registry,
92 > exec.executeScheduleToCloseTimeoutTask,
93 > ); err != nil {
94 return err
95 }
96 > if err := hsm.RegisterTimerExecutor( executors.go
97 > registry,
98 > exec.executeScheduleToStartTimeoutTask,
99 > ); err != nil {
100 return err
101 }
102 > if err := hsm.RegisterTimerExecutor( executors.go
103 > registry,
104 > exec.executeStartToCloseTimeoutTask,
105 > ); err != nil {
106 return err
107 }
108 > if err := hsm.RegisterImmediateExecutor( executors.go
109 > registry,
110 > exec.executeCancelationTask,
111 > ); err != nil {
112 return err
113 }
114 > return hsm.RegisterTimerExecutor( executors.go
115 > registry,
116 > exec.executeCancelationBackoffTask,
117 > )
118 }
119
go.temporal.io/server/service/history/tasks/key.go 30 covered LOC · 15 ranges

Open complete file

28 )
29
30 > func NewImmediateKey(taskID int64) Key { key.go
31 > return Key{
32 > FireTime: DefaultFireTime,
33 > TaskID: taskID,
34 > }
35 > }
36
37 > func NewKey(fireTime time.Time, taskID int64) Key { key.go
38 > return Key{
39 > FireTime: fireTime,
40 > TaskID: taskID,
41 > }
42 > }
43
44 func ValidateKey(key Key) error {
54 }
55
56 > func (left Key) CompareTo(right Key) int { key.go
57 > if left.FireTime.Before(right.FireTime) {
58 > return -1 key.go
59 > } else if left.FireTime.After(right.FireTime) { key.go
60 > return 1 key.go
61 > }
62
63 > if left.TaskID < right.TaskID { key.go
64 > return -1 key.go
65 > } else if left.TaskID > right.TaskID { key.go
66 > return 1 key.go
67 > }
68 > return 0 key.go
69 }
70
79 }
80
81 > func (k Key) Next() Key { key.go
82 > if k.TaskID == math.MaxInt64 {
83 if k.FireTime.UnixNano() == math.MaxInt64 {
84 panic("Key encountered positive overflow")
86 return NewKey(k.FireTime.Add(time.Nanosecond), 0)
87 }
88 > return NewKey(k.FireTime, k.TaskID+1) key.go
89 }
90
109 }
110
111 > func MinKey(this Key, that Key) Key { key.go
112 > if this.CompareTo(that) < 0 {
113 return this
114 }
115 > return that key.go
116 }
117
go.temporal.io/server/api/taskqueue/v1/message.pb.go 29 covered LOC · 2 ranges

Open complete file

1330 }
1331
1332 > func init() { file_temporal_server_api_taskqueue_v1_message_proto_init() } message.pb.go
1333 > func file_temporal_server_api_taskqueue_v1_message_proto_init() {
1334 > if File_temporal_server_api_taskqueue_v1_message_proto != nil {
1335 return
1336 }
1337 > file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[0].OneofWrappers = []any{ message.pb.go
1338 > (*TaskVersionDirective_UseAssignmentRules)(nil),
1339 > (*TaskVersionDirective_AssignedBuildId)(nil),
1340 > }
1341 > file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[5].OneofWrappers = []any{
1342 > (*TaskQueuePartition_NormalPartitionId)(nil),
1343 > (*TaskQueuePartition_StickyName)(nil),
1344 > (*TaskQueuePartition_WorkerCommands)(nil),
1345 > }
1346 > type x struct{}
1347 > out := protoimpl.TypeBuilder{
1348 > File: protoimpl.DescBuilder{
1349 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1350 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_taskqueue_v1_message_proto_rawDesc), len(file_temporal_server_api_taskqueue_v1_message_proto_rawDesc)),
1351 > NumEnums: 0,
1352 > NumMessages: 16,
1353 > NumExtensions: 0,
1354 > NumServices: 0,
1355 > },
1356 > GoTypes: file_temporal_server_api_taskqueue_v1_message_proto_goTypes,
1357 > DependencyIndexes: file_temporal_server_api_taskqueue_v1_message_proto_depIdxs,
1358 > MessageInfos: file_temporal_server_api_taskqueue_v1_message_proto_msgTypes,
1359 > }.Build()
1360 > File_temporal_server_api_taskqueue_v1_message_proto = out.File
1361 > file_temporal_server_api_taskqueue_v1_message_proto_goTypes = nil
1362 > file_temporal_server_api_taskqueue_v1_message_proto_depIdxs = nil
1363 }
go.temporal.io/server/common/log/sdk_logger.go 29 covered LOC · 13 ranges

Open complete file

19 var _ log.Logger = (*SdkLogger)(nil)
20
21 > func NewSdkLogger(logger Logger) *SdkLogger { sdk_logger.go
22 > if sl, ok := logger.(SkipLogger); ok {
23 logger = sl.Skip(extraSkipForSdkLogger)
24 }
25
26 > return &SdkLogger{ sdk_logger.go
27 > logger: logger,
28 > }
29 }
30
31 > func (l *SdkLogger) tags(keyvals []any) []tag.Tag { sdk_logger.go
32 > var tags []tag.Tag
33 > for i := 0; i < len(keyvals); i++ {
34 > if t, keyvalIsTag := keyvals[i].(tag.Tag); keyvalIsTag { sdk_logger.go
35 tags = append(tags, t)
36 continue
37 }
38
39 > key, keyIsString := keyvals[i].(string) sdk_logger.go
40 > if !keyIsString {
41 key = fmt.Sprintf("%v", keyvals[i])
42 }
43 > var val any sdk_logger.go
44 > if i+1 == len(keyvals) {
45 val = noValue
46 > } else { sdk_logger.go
47 > val = keyvals[i+1] sdk_logger.go
48 > i++
49 > }
50
51 > tags = append(tags, tag.Any(key, val)) sdk_logger.go
52 }
53
54 > return tags sdk_logger.go
55 }
56
59 }
60
61 > func (l *SdkLogger) Info(msg string, keyvals ...any) { sdk_logger.go
62 > l.logger.Info(msg, l.tags(keyvals)...)
63 > }
64
65 > func (l *SdkLogger) Warn(msg string, keyvals ...any) { sdk_logger.go
66 > l.logger.Warn(msg, l.tags(keyvals)...)
67 > }
68
69 func (l *SdkLogger) Error(msg string, keyvals ...any) {
71 }
72
73 > func (l *SdkLogger) With(keyvals ...any) log.Logger { sdk_logger.go
74 > return NewSdkLogger(
75 > With(l.logger, l.tags(keyvals)...))
76 > }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/conn_pool.go 29 covered LOC · 9 ranges

Open complete file

23 }
24
25 > func newConnPool() *connPool { conn_pool.go
26 > return &connPool{
27 > pool: make(map[string]entry),
28 > }
29 > }
30
31 // Allocate allocates the shared database in the pool or returns already exists instance with the same DSN. If instance
36 logger log.Logger,
37 create func(*config.SQL, resolver.ServiceResolver, log.Logger) (*sqlx.DB, error),
38 > ) (db *sqlx.DB, err error) { conn_pool.go
39 > cp.mu.Lock()
40 > defer cp.mu.Unlock()
41 >
42 > dsn, err := buildDSN(cfg)
43 > if err != nil {
44 return nil, err
45 }
46
47 > if entry, ok := cp.pool[dsn]; ok { conn_pool.go
48 > entry.refCount++ conn_pool.go
49 > return entry.db, nil
50 > }
51
52 > db, err = create(cfg, resolver, logger) conn_pool.go
53 > if err != nil {
54 return nil, err
55 }
56
57 > cp.pool[dsn] = entry{db: db, refCount: 1} conn_pool.go
58 >
59 > return db, nil
60 }
61
62 // Close virtual connection to database. Only closes for real once no references left.
63 > func (cp *connPool) Close(cfg *config.SQL) { conn_pool.go
64 > cp.mu.Lock()
65 > defer cp.mu.Unlock()
66 >
67 > dsn, err := buildDSN(cfg)
68 > if err != nil {
69 return
70 }
71
72 > e, ok := cp.pool[dsn] conn_pool.go
73 > if !ok {
74 // no such database
75 return
76 }
77
78 > e.refCount-- conn_pool.go
79 // todo: at the moment pool will persist a single connection to the DB for the whole duration of application
80 // temporal will start and stop DB connections multiple times, which will cause the loss of the cache
go.temporal.io/server/common/rpc/interceptor/concurrent_request_limit.go 29 covered LOC · 5 ranges

Open complete file

50 globalQuota func(ns string) int,
51 tokens map[string]int,
52 > ) *ConcurrentRequestLimitInterceptor { concurrent_request_limit.go
53 > return &ConcurrentRequestLimitInterceptor{
54 > namespaceRegistry: namespaceRegistry,
55 > logger: logger,
56 > quotaCalculator: calculator.NewLoggedNamespaceCalculator(
57 > calculator.ClusterAwareNamespaceQuotaCalculator{
58 > MemberCounter: memberCounter,
59 > PerInstanceQuota: perInstanceQuota,
60 > GlobalQuota: globalQuota,
61 > },
62 > log.With(logger, tag.ComponentLongPollHandler, tag.ScopeNamespace),
63 > ),
64 > tokens: tokens,
65 > activeTokensCount: make(map[string]*int32),
66 > }
67 > }
68
69 func (ni *ConcurrentRequestLimitInterceptor) Intercept(
72 info *grpc.UnaryServerInfo,
73 handler grpc.UnaryHandler,
74 > ) (any, error) { concurrent_request_limit.go
75 > nsName := MustGetNamespaceName(ni.namespaceRegistry, req)
76 > mh := GetMetricsHandlerFromContext(ctx, ni.logger)
77 > cleanup, err := ni.Allow(nsName, info.FullMethod, mh, req)
78 > defer cleanup()
79 > if err != nil {
80 return nil, err
81 }
82
83 > return handler(ctx, req) concurrent_request_limit.go
84 }
85
89 mh metrics.Handler,
90 req any,
91 > ) (func(), error) { concurrent_request_limit.go
92 > // token will default to 0
93 > token := ni.tokens[methodName]
94 >
95 > if token == 0 {
96 > return func() {}, nil concurrent_request_limit.go
97 }
98 // for GetWorkflowExecutionHistoryRequest, we only care about long poll requests
go.temporal.io/server/common/rpc/interceptor/rate_limit.go 29 covered LOC · 9 ranges

Open complete file

37 rateLimiter quotas.RequestRateLimiter,
38 tokens map[string]int,
39 > ) *RateLimitInterceptor { rate_limit.go
40 > return &RateLimitInterceptor{
41 > rateLimiter: rateLimiter,
42 > tokens: tokens,
43 > }
44 > }
45
46 func (i *RateLimitInterceptor) Intercept(
49 info *grpc.UnaryServerInfo,
50 handler grpc.UnaryHandler,
51 > ) (any, error) { rate_limit.go
52 > methodName := info.FullMethod
53 >
54 > // for DescribeTaskQueueRequest, we want to use visibility rate limit only if reachability is queried
55 > describeTQReq, ok := req.(*workflowservice.DescribeTaskQueueRequest)
56 > if ok && describeTQReq.GetReportTaskReachability() {
57 methodName += "WithReachability"
58 }
59
60 > if err := i.Allow(methodName, headers.NewGRPCHeaderGetter(ctx)); err != nil { rate_limit.go
61 return nil, err
62 }
63
64 > return handler(ctx, req) rate_limit.go
65 }
66
68 methodName string,
69 headerGetter headers.HeaderGetter,
70 > ) error { rate_limit.go
71 > token, ok := i.tokens[methodName]
72 > if !ok {
73 > token = RateLimitDefaultToken rate_limit.go
74 > }
75
76 // we don't want to apply rate limiter if a method is configured with 0 tokens.
77 > if token < 1 { rate_limit.go
78 return nil
79 }
80
81 > if !i.rateLimiter.Allow(time.Now().UTC(), quotas.NewRequest( rate_limit.go
82 > methodName,
83 > token,
84 > headerGetter.Get(headers.CallerNameHeaderName),
85 > headerGetter.Get(headers.CallerTypeHeaderName),
86 > 0, // this interceptor layer does not throttle based on caller segment
87 > "", // this interceptor layer does not throttle based on call initiation
88 > )) {
89 return RateLimitServerBusy
90 }
91 > return nil rate_limit.go
92 }
go.temporal.io/server/common/tasks/execution_aware_scheduler.go 29 covered LOC · 3 ranges

Open complete file

50 metricsHandler metrics.Handler,
51 timeSource clock.TimeSource,
52 > ) *ExecutionAwareScheduler[T] { execution_aware_scheduler.go
53 > return &ExecutionAwareScheduler[T]{
54 > baseScheduler: baseScheduler,
55 > executionQueueScheduler: newExecutionQueueScheduler(
56 > options.MaxQueues,
57 > options.QueueTTL,
58 > options.QueueConcurrency,
59 > queueKeyFn,
60 > logger,
61 > metricsHandler,
62 > timeSource,
63 > ),
64 > queueKeyFn: queueKeyFn,
65 > options: options,
66 > logger: logger,
67 > }
68 > }
69
70 > func (s *ExecutionAwareScheduler[T]) Start() { execution_aware_scheduler.go
71 > s.baseScheduler.Start()
72 > // Always start the executionQueueScheduler regardless of current config.
73 > // The Enabled check gates task routing, so an idle scheduler has minimal
74 > // overhead. This ensures if the config changes from disabled to enabled,
75 > // tasks will be processed correctly.
76 > s.executionQueueScheduler.Start()
77 > }
78
79 > func (s *ExecutionAwareScheduler[T]) Stop() { execution_aware_scheduler.go
80 > s.baseScheduler.Stop()
81 > s.executionQueueScheduler.Stop()
82 > }
83
84 func (s *ExecutionAwareScheduler[T]) Submit(task T) {
go.temporal.io/server/components/nexusoperations/tasks.go 29 covered LOC · 14 ranges

Open complete file

35 var _ hsm.Task = ScheduleToCloseTimeoutTask{}
36
37 > func (ScheduleToCloseTimeoutTask) Type() string { tasks.go
38 > return TaskTypeScheduleToCloseTimeout
39 > }
40
41 func (t ScheduleToCloseTimeoutTask) Deadline() time.Time {
84 var _ hsm.Task = InvocationTask{}
85
86 > func (InvocationTask) Type() string { tasks.go
87 > return TaskTypeInvocation
88 > }
89
90 func (InvocationTask) Deadline() time.Time {
129 var _ hsm.Task = BackoffTask{}
130
131 > func (BackoffTask) Type() string { tasks.go
132 > return TaskTypeBackoff
133 > }
134
135 func (t BackoffTask) Deadline() time.Time {
165 var _ hsm.Task = CancelationTask{}
166
167 > func (CancelationTask) Type() string { tasks.go
168 > return TaskTypeCancelation
169 > }
170
171 func (CancelationTask) Deadline() time.Time {
210 var _ hsm.Task = CancelationBackoffTask{}
211
212 > func (CancelationBackoffTask) Type() string { tasks.go
213 > return TaskTypeCancelationBackoff
214 > }
215
216 func (t CancelationBackoffTask) Deadline() time.Time {
245 var _ hsm.Task = ScheduleToStartTimeoutTask{}
246
247 > func (ScheduleToStartTimeoutTask) Type() string { tasks.go
248 > return TaskTypeScheduleToStartTimeout
249 > }
250
251 func (t ScheduleToStartTimeoutTask) Deadline() time.Time {
299 var _ hsm.Task = StartToCloseTimeoutTask{}
300
301 > func (StartToCloseTimeoutTask) Type() string { tasks.go
302 > return TaskTypeStartToCloseTimeout
303 > }
304
305 func (t StartToCloseTimeoutTask) Deadline() time.Time {
343 }
344
345 > func RegisterTaskSerializers(reg *hsm.Registry) error { tasks.go
346 > if err := reg.RegisterTaskSerializer(TaskTypeScheduleToCloseTimeout, TimeoutTaskSerializer{}); err != nil {
347 return err
348 }
349 > if err := reg.RegisterTaskSerializer(TaskTypeInvocation, InvocationTaskSerializer{}); err != nil { tasks.go
350 return err
351 }
352 > if err := reg.RegisterTaskSerializer(TaskTypeBackoff, BackoffTaskSerializer{}); err != nil { tasks.go
353 return err
354 }
355 > if err := reg.RegisterTaskSerializer(TaskTypeCancelation, CancelationTaskSerializer{}); err != nil { tasks.go
356 return err
357 }
358 > if err := reg.RegisterTaskSerializer(TaskTypeCancelationBackoff, CancelationBackoffTaskSerializer{}); err != nil { // nolint:revive tasks.go
359 return err
360 }
361 > if err := reg.RegisterTaskSerializer(TaskTypeScheduleToStartTimeout, ScheduleToStartTimeoutTaskSerializer{}); err != nil { tasks.go
362 return err
363 }
364 > return reg.RegisterTaskSerializer(TaskTypeStartToCloseTimeout, StartToCloseTimeoutTaskSerializer{}) tasks.go
365 }
go.temporal.io/server/api/history/v1/message.pb.go 28 covered LOC · 6 ranges

Open complete file

92 func (*VersionHistoryItem) ProtoMessage() {}
93
94 > func (x *VersionHistoryItem) ProtoReflect() protoreflect.Message { message.pb.go
95 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[1]
96 > if x != nil {
97 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
98 if ms.LoadMessageInfo() == nil {
101 return ms
102 }
103 > return mi.MessageOf(x) message.pb.go
104 }
105
198 func (*VersionHistories) ProtoMessage() {}
199
200 > func (x *VersionHistories) ProtoReflect() protoreflect.Message { message.pb.go
201 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[3]
202 > if x != nil {
203 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
204 if ms.LoadMessageInfo() == nil {
207 return ms
208 }
209 > return mi.MessageOf(x) message.pb.go
210 }
211
498 }
499
500 > func init() { file_temporal_server_api_history_v1_message_proto_init() } message.pb.go
501 > func file_temporal_server_api_history_v1_message_proto_init() {
502 > if File_temporal_server_api_history_v1_message_proto != nil {
503 return
504 }
505 > type x struct{} message.pb.go
506 > out := protoimpl.TypeBuilder{
507 > File: protoimpl.DescBuilder{
508 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
509 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_history_v1_message_proto_rawDesc), len(file_temporal_server_api_history_v1_message_proto_rawDesc)),
510 > NumEnums: 0,
511 > NumMessages: 8,
512 > NumExtensions: 0,
513 > NumServices: 0,
514 > },
515 > GoTypes: file_temporal_server_api_history_v1_message_proto_goTypes,
516 > DependencyIndexes: file_temporal_server_api_history_v1_message_proto_depIdxs,
517 > MessageInfos: file_temporal_server_api_history_v1_message_proto_msgTypes,
518 > }.Build()
519 > File_temporal_server_api_history_v1_message_proto = out.File
520 > file_temporal_server_api_history_v1_message_proto_goTypes = nil
521 > file_temporal_server_api_history_v1_message_proto_depIdxs = nil
522 }
go.temporal.io/server/api/persistence/v1/queue_metadata.pb.go 28 covered LOC · 3 ranges

Open complete file

44 func (*QueueMetadata) ProtoMessage() {}
45
46 > func (x *QueueMetadata) ProtoReflect() protoreflect.Message { queue_metadata.pb.go
47 > mi := &file_temporal_server_api_persistence_v1_queue_metadata_proto_msgTypes[0]
48 > if x != nil {
49 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
50 > if ms.LoadMessageInfo() == nil {
51 > ms.StoreMessageInfo(mi)
52 > }
53 > return ms
54 }
55 return mi.MessageOf(x)
105 }
106
107 > func init() { file_temporal_server_api_persistence_v1_queue_metadata_proto_init() } queue_metadata.pb.go
108 > func file_temporal_server_api_persistence_v1_queue_metadata_proto_init() {
109 > if File_temporal_server_api_persistence_v1_queue_metadata_proto != nil {
110 return
111 }
112 > type x struct{} queue_metadata.pb.go
113 > out := protoimpl.TypeBuilder{
114 > File: protoimpl.DescBuilder{
115 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
116 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_queue_metadata_proto_rawDesc), len(file_temporal_server_api_persistence_v1_queue_metadata_proto_rawDesc)),
117 > NumEnums: 0,
118 > NumMessages: 2,
119 > NumExtensions: 0,
120 > NumServices: 0,
121 > },
122 > GoTypes: file_temporal_server_api_persistence_v1_queue_metadata_proto_goTypes,
123 > DependencyIndexes: file_temporal_server_api_persistence_v1_queue_metadata_proto_depIdxs,
124 > MessageInfos: file_temporal_server_api_persistence_v1_queue_metadata_proto_msgTypes,
125 > }.Build()
126 > File_temporal_server_api_persistence_v1_queue_metadata_proto = out.File
127 > file_temporal_server_api_persistence_v1_queue_metadata_proto_goTypes = nil
128 > file_temporal_server_api_persistence_v1_queue_metadata_proto_depIdxs = nil
129 }
go.temporal.io/server/chasm/lib/nexusoperation/fx.go 28 covered LOC · 7 ranges

Open complete file

62 registry *chasm.Registry,
63 library *Library,
64 > ) error { fx.go
65 > return registry.Register(library)
66 > }
67
68 func endpointRegistryProvider(
72 logger log.Logger,
73 metricsHandler metrics.Handler,
74 > ) commonnexus.EndpointRegistry { fx.go
75 > registryConfig := commonnexus.NewEndpointRegistryConfig(dc)
76 > return commonnexus.NewEndpointRegistry(
77 > registryConfig,
78 > matchingClient,
79 > endpointManager,
80 > logger,
81 > metricsHandler,
82 > )
83 > }
84
85 > func endpointRegistryLifetimeHooks(lc fx.Lifecycle, registry commonnexus.EndpointRegistry) { fx.go
86 > lc.Append(fx.StartStopHook(registry.StartLifecycle, registry.StopLifecycle))
87 > }
88
89 // NexusTransportProvider allows customization of the HTTP transport used for Nexus requests.
90 type NexusTransportProvider func(namespaceID, serviceName string) http.RoundTripper
91
92 > func defaultNexusTransportProvider() NexusTransportProvider { fx.go
93 > return func(namespaceID, serviceName string) http.RoundTripper {
94 return http.DefaultTransport
95 }
119 clusterMetadata cluster.Metadata,
120 rpcFactory common.RPCFactory,
121 > ) (ClientProvider, error) { fx.go
122 > cl, err := rpcFactory.CreateLocalFrontendHTTPClient()
123 > if err != nil {
124 return nil, fmt.Errorf("cannot create local frontend HTTP client: %w", err)
125 }
126 > var clusterID string fx.go
127 >
128 > if clusterInfo, ok := clusterMetadata.GetAllClusterInfo()[clusterMetadata.GetCurrentClusterName()]; ok {
129 > clusterID = clusterInfo.ClusterID
130 > }
131 > m := collection.NewFallibleOnceMap(func(key clientProviderCacheKey) (*http.Client, error) {
132 transport := httpTransportProvider(key.namespaceID, key.endpointID)
133 return &http.Client{
136 })
137
138 > return func(ctx context.Context, namespaceID string, entry *persistencespb.NexusEndpointEntry, service string) (*nexusrpc.HTTPClient, error) { fx.go
139 var url string
140 var httpClient *http.Client
go.temporal.io/server/chasm/nexus_operation_processor.go 28 covered LOC · 9 ranges

Open complete file

79 }
80
81 > func nexusOperationProcessorAdapter[I any](processor NexusOperationProcessor[I]) func(ctx NexusOperationProcessorContext, input *commonpb.Payload) (*NexusOperationProcessorResult, error) { nexus_operation_processor.go
82 > return func(ctx NexusOperationProcessorContext, input *commonpb.Payload) (*NexusOperationProcessorResult, error) {
83 var i I
84 if err := sdkconverter.PreferProtoDataConverter.FromPayloads(&commonpb.Payloads{Payloads: []*commonpb.Payload{input}}, &i); err != nil {
105
106 // NewRegisterableNexusOperationProcessor wraps a typed NexusOperationProcessor and returns a registerable adapter.
107 > func NewRegisterableNexusOperationProcessor[I any](op NexusOperationProcessor[I]) RegisterableNexusOperationProcessor { nexus_operation_processor.go
108 > return RegisterableNexusOperationProcessor{
109 > processInput: nexusOperationProcessorAdapter(op),
110 > }
111 > }
112
113 // NexusServiceProcessor handles input processing for operations within a specific Nexus service.
120 // NewNexusServiceProcessor constructs a processor for a single Nexus service that can register and invoke operation
121 // processors by name.
122 > func NewNexusServiceProcessor(name string) *NexusServiceProcessor { nexus_operation_processor.go
123 > return &NexusServiceProcessor{
124 > name: name,
125 > operations: make(map[string]RegisterableNexusOperationProcessor),
126 > }
127 > }
128
129 // RegisterOperation registers a named operation with this service processor.
130 // Returns an error if an operation with the same name is already registered.
131 > func (p *NexusServiceProcessor) RegisterOperation(name string, op RegisterableNexusOperationProcessor) error { nexus_operation_processor.go
132 > if _, exists := p.operations[name]; exists {
133 return fmt.Errorf("operation %q already registered", name)
134 }
135 > p.operations[name] = op nexus_operation_processor.go
136 > return nil
137 }
138
139 // MustRegisterOperation registers a named operation and panics if registration fails.
140 > func (p *NexusServiceProcessor) MustRegisterOperation(name string, op RegisterableNexusOperationProcessor) { nexus_operation_processor.go
141 > if err := p.RegisterOperation(name, op); err != nil {
142 // nolint:forbidigo // Panic is acceptable here for Must-style method.
143 panic(err)
165
166 // NewNexusEndpointProcessor creates a new NexusEndpointProcessor.
167 > func NewNexusEndpointProcessor() *NexusEndpointProcessor { nexus_operation_processor.go
168 > return &NexusEndpointProcessor{
169 > serviceProcessors: make(map[string]*NexusServiceProcessor),
170 > }
171 > }
172
173 // RegisterServiceProcessor adds a service-level processor to the endpoint keyed by its name.
174 // Returns an error if a processor with the same name is already registered.
175 > func (p *NexusEndpointProcessor) RegisterServiceProcessor(processor *NexusServiceProcessor) error { nexus_operation_processor.go
176 > if _, exists := p.serviceProcessors[processor.name]; exists {
177 return fmt.Errorf("service processor %q already registered", processor.name)
178 }
179 > p.serviceProcessors[processor.name] = processor nexus_operation_processor.go
180 > return nil
181 }
182
go.temporal.io/server/common/persistence/sql/common.go 28 covered LOC · 9 ranges

Open complete file

25 }
26
27 > func NewSQLStore(db sqlplugin.DB, logger log.Logger, serializer serialization.Serializer) SqlStore { common.go
28 > return SqlStore{
29 > DB: db,
30 > logger: logger,
31 > serializer: serializer,
32 > }
33 > }
34
35 > func (m *SqlStore) GetName() string { common.go
36 > return m.DB.PluginName()
37 > }
38
39 > func (m *SqlStore) GetDbName() string { common.go
40 > return m.DB.DbName()
41 > }
42
43 > func (m *SqlStore) Close() { common.go
44 > if m.DB != nil {
45 > err := m.DB.Close()
46 > if err != nil {
47 m.logger.Error("Error closing SQL database", tag.Error(err))
48 }
50 }
51
52 > func (m *SqlStore) txExecute(ctx context.Context, operation string, f func(tx sqlplugin.Tx) error) error { common.go
53 > tx, err := m.DB.BeginTx(ctx)
54 > if err != nil {
55 return serviceerror.NewUnavailablef("%s failed. Failed to start transaction. Error: %v", operation, err)
56 }
57 > err = f(tx) common.go
58 > if err != nil {
59 rollBackErr := tx.Rollback()
60 if rollBackErr != nil {
75 }
76 }
77 > if err := tx.Commit(); err != nil { common.go
78 return serviceerror.NewUnavailablef("%s operation failed. Failed to commit transaction. Error: %v", operation, err)
79 }
80 > return nil common.go
81 }
82
129 operation string,
130 err error,
131 > ) error { common.go
132 > if err == sql.ErrNoRows {
133 > return serviceerror.NewNotFoundf("%v failed. Error: %v ", operation, err)
134 > }
135
136 return serviceerror.NewUnavailablef("%v operation failed. Error: %v", operation, err)
go.temporal.io/server/service/history/events/notifier.go 28 covered LOC · 8 ranges

Open complete file

104 metricsHandler metrics.Handler,
105 workflowIDToShardID func(namespace.ID, string) int32,
106 > ) *NotifierImpl { notifier.go
107 >
108 > hashFn := func(key any) uint32 {
109 notification, ok := key.(Notification)
110 if !ok {
113 return uint32(workflowIDToShardID(namespace.ID(notification.ID.NamespaceID), notification.ID.WorkflowID))
114 }
115 > return &NotifierImpl{ notifier.go
116 > timeSource: timeSource,
117 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.HistoryEventNotificationScope)),
118 > status: common.DaemonStatusInitialized,
119 > closeChan: make(chan bool),
120 > eventsChan: make(chan *Notification, eventsChanSize),
121 >
122 > workflowIDToShardID: workflowIDToShardID,
123 >
124 > eventsPubsubs: collection.NewShardedConcurrentTxMap(1024, hashFn),
125 > }
126 }
127
212 }
213
214 > func (notifier *NotifierImpl) dequeueHistoryEventNotifications() { notifier.go
215 > for {
216 > // send out metrics about the current number of messages in flight
217 > metrics.HistoryEventNotificationInFlightMessageGauge.With(notifier.metricsHandler).Record(float64(len(notifier.eventsChan)))
218 > select {
219 case event := <-notifier.eventsChan:
220 // send out metrics about message processing delay
223
224 notifier.dispatchHistoryEventNotification(event)
225 > case <-notifier.closeChan: notifier.go
226 > // shutdown
227 > return
228 }
229 }
230 }
231
232 > func (notifier *NotifierImpl) Start() { notifier.go
233 > if !atomic.CompareAndSwapInt32(&notifier.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
234 return
235 }
236 > go notifier.dequeueHistoryEventNotifications() notifier.go
237 }
238
239 > func (notifier *NotifierImpl) Stop() { notifier.go
240 > if !atomic.CompareAndSwapInt32(&notifier.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
241 return
242 }
243 > close(notifier.closeChan) notifier.go
244 }
245
go.temporal.io/server/api/persistence/v1/queues.pb.go 27 covered LOC · 3 ranges

Open complete file

98 func (*QueueState) ProtoMessage() {}
99
100 > func (x *QueueState) ProtoReflect() protoreflect.Message { queues.pb.go
101 > mi := &file_temporal_server_api_persistence_v1_queues_proto_msgTypes[1]
102 > if x != nil {
103 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
104 if ms.LoadMessageInfo() == nil {
107 return ms
108 }
109 > return mi.MessageOf(x) queues.pb.go
110 }
111
616 }
617
618 > func init() { file_temporal_server_api_persistence_v1_queues_proto_init() } queues.pb.go
619 > func file_temporal_server_api_persistence_v1_queues_proto_init() {
620 > if File_temporal_server_api_persistence_v1_queues_proto != nil {
621 > return
622 > }
623 > file_temporal_server_api_persistence_v1_predicates_proto_init()
624 > type x struct{}
625 > out := protoimpl.TypeBuilder{
626 > File: protoimpl.DescBuilder{
627 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
628 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_queues_proto_rawDesc), len(file_temporal_server_api_persistence_v1_queues_proto_rawDesc)),
629 > NumEnums: 0,
630 > NumMessages: 12,
631 > NumExtensions: 0,
632 > NumServices: 0,
633 > },
634 > GoTypes: file_temporal_server_api_persistence_v1_queues_proto_goTypes,
635 > DependencyIndexes: file_temporal_server_api_persistence_v1_queues_proto_depIdxs,
636 > MessageInfos: file_temporal_server_api_persistence_v1_queues_proto_msgTypes,
637 > }.Build()
638 > File_temporal_server_api_persistence_v1_queues_proto = out.File
639 > file_temporal_server_api_persistence_v1_queues_proto_goTypes = nil
640 > file_temporal_server_api_persistence_v1_queues_proto_depIdxs = nil
641 }
go.temporal.io/server/chasm/lib/workflow/nexus_events.go 27 covered LOC · 9 ranges

Open complete file

19 }
20
21 > func (d ScheduledEventDefinition) Type() enumspb.EventType { nexus_events.go
22 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED
23 > }
24
25 func (d ScheduledEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
75 }
76
77 > func (d CancelRequestedEventDefinition) Type() enumspb.EventType { nexus_events.go
78 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED
79 > }
80
81 func (d CancelRequestedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
113 }
114
115 > func (d CancelRequestCompletedEventDefinition) Type() enumspb.EventType { nexus_events.go
116 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_COMPLETED
117 > }
118
119 func (d CancelRequestCompletedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
143 }
144
145 > func (d CancelRequestFailedEventDefinition) Type() enumspb.EventType { nexus_events.go
146 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED
147 > }
148
149 func (d CancelRequestFailedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
175 }
176
177 > func (d StartedEventDefinition) Type() enumspb.EventType { nexus_events.go
178 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_STARTED
179 > }
180
181 func (d StartedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
209 }
210
211 > func (d CompletedEventDefinition) Type() enumspb.EventType { nexus_events.go
212 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_COMPLETED
213 > }
214
215 func (d CompletedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
247 }
248
249 > func (d FailedEventDefinition) Type() enumspb.EventType { nexus_events.go
250 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_FAILED
251 > }
252
253 func (d FailedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
285 }
286
287 > func (d CanceledEventDefinition) Type() enumspb.EventType { nexus_events.go
288 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCELED
289 > }
290
291 func (d CanceledEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
323 }
324
325 > func (d TimedOutEventDefinition) Type() enumspb.EventType { nexus_events.go
326 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_TIMED_OUT
327 > }
328
329 func (d TimedOutEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
go.temporal.io/server/common/goro/goro.go 27 covered LOC · 8 ranges

Open complete file

22 // the goroutine starts, which makes it possible for the goroutine to call
23 // Done() on itself (maybe indirectly) without a race condition.
24 > func NewHandle(ctx context.Context) *Handle { goro.go
25 > ctx, cancel := context.WithCancel(ctx)
26 > return &Handle{
27 > context: ctx,
28 > cancel: cancel,
29 > done: make(chan struct{}),
30 > }
31 > }
32
33 // Go launches the supplied function in its own goroutine. Go should be called
34 // exactly once on each *Handle.
35 > func (h *Handle) Go(f func(context.Context) error) *Handle { goro.go
36 > go func() {
37 > // use defer here so that the channel is closed even if the func calls
38 > // runtime.Goexit()
39 > defer close(h.done)
40 > if err := f(h.context); err != nil {
41 > h.err.Store(err) goro.go
42 > }
43 }()
44 > return h goro.go
45 }
46
49 // the Done() channel closing is the time taken by the goroutine to shut itself
50 // down.
51 > func (h *Handle) Done() <-chan struct{} { goro.go
52 > return h.done
53 > }
54
55 // Cancel requests that this goroutine stop by cancelling the associated context
56 // object. This function is threadsafe and idempotent. Note that this function
57 // _requests_ termination, it does not forcefully kill the goroutine.
58 > func (h *Handle) Cancel() { goro.go
59 > h.cancel()
60 > }
61
62 // Error observes the error returned by the func passed to Go (if any). There is
63 // never any error (i.e. this function returns nil) while the goroutine is
64 // running.
65 > func (h *Handle) Err() error { goro.go
66 > v := h.err.Load()
67 > if v == nil {
68 return nil
69 }
70 > return v.(error) goro.go
71 }
go.temporal.io/server/common/rpc/interceptor/mask_internal_error.go 27 covered LOC · 7 ranges

Open complete file

32 namespaceRegistry namespace.Registry,
33 logger log.Logger,
34 > ) *MaskInternalErrorDetailsInterceptor { mask_internal_error.go
35 >
36 > return &MaskInternalErrorDetailsInterceptor{
37 > maskInternalError: maskErrorSetting,
38 > namespaceRegistry: namespaceRegistry,
39 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
40 > logger: logger,
41 > }
42 > }
43
44 func (mi *MaskInternalErrorDetailsInterceptor) Intercept(
47 info *grpc.UnaryServerInfo,
48 handler grpc.UnaryHandler,
49 > ) (any, error) { mask_internal_error.go
50 >
51 > resp, err := handler(ctx, req)
52 >
53 > if err != nil && mi.shouldMaskErrors(req) {
54 > err = mi.maskUnknownOrInternalErrors(req, info.FullMethod, err) mask_internal_error.go
55 > }
56 > return resp, err mask_internal_error.go
57 }
58
59 > func (mi *MaskInternalErrorDetailsInterceptor) shouldMaskErrors(req any) bool { mask_internal_error.go
60 > ns := MustGetNamespaceName(mi.namespaceRegistry, req)
61 > if ns.IsEmpty() {
62 return false
63 }
64 > return mi.maskInternalError(ns.String()) mask_internal_error.go
65 }
66
67 func (mi *MaskInternalErrorDetailsInterceptor) maskUnknownOrInternalErrors(
68 req any, fullMethodName string, err error,
69 > ) error { mask_internal_error.go
70 > statusCode := serviceerror.ToStatus(err).Code()
71 >
72 > if statusCode != codes.Unknown && statusCode != codes.Internal {
73 > return err
74 > }
75
76 // we need to log the original error with hash.
go.temporal.io/server/common/rpc/interceptor/namespace_handover.go 27 covered LOC · 6 ranges

Open complete file

52 requestErrorHandler ErrorHandler,
53 additionalAllowedMethodsDuringHandover []string,
54 > ) *NamespaceHandoverInterceptor { namespace_handover.go
55 >
56 > additional := make(map[string]struct{}, len(additionalAllowedMethodsDuringHandover))
57 > for _, m := range additionalAllowedMethodsDuringHandover {
58 additional[m] = struct{}{}
59 }
60
61 > return &NamespaceHandoverInterceptor{ namespace_handover.go
62 > enabledForNS: dynamicconfig.EnableNamespaceHandoverWait.Get(dc),
63 > nsCacheRefreshInterval: dynamicconfig.NamespaceCacheRefreshInterval.Get(dc),
64 > namespaceRegistry: namespaceRegistry,
65 > metricsHandler: metricsHandler,
66 > logger: logger,
67 > timeSource: timeSource,
68 > requestErrorHandler: requestErrorHandler,
69 > additionalAllowedMethodsDuringHandover: additional,
70 > }
71 }
72
82 // handlesMethod reports whether the handover gate applies to fullMethod: always for WorkflowService,
83 // plus any embedder-configured service prefixes.
84 > func (i *NamespaceHandoverInterceptor) handlesMethod(fullMethod string) bool { namespace_handover.go
85 > if strings.HasPrefix(fullMethod, api.WorkflowServicePrefix) {
86 > return true
87 > }
88 for _, prefix := range i.additionalServicePrefixes {
89 if strings.HasPrefix(fullMethod, prefix) {
99 info *grpc.UnaryServerInfo,
100 handler grpc.UnaryHandler,
101 > ) (_ any, retError error) { namespace_handover.go
102 > defer log.CapturePanic(i.logger, &retError)
103 >
104 > if !i.handlesMethod(info.FullMethod) {
105 return handler(ctx, req)
106 }
107
108 // review which method is allowed
109 > methodName := api.MethodName(info.FullMethod) namespace_handover.go
110 > namespaceName := MustGetNamespaceName(i.namespaceRegistry, req)
111 >
112 > if namespaceName != namespace.EmptyName && i.enabledForNS(namespaceName.String()) {
113 var waitTime *time.Duration
114 defer func() {
go.temporal.io/server/service/history/replication/dlq_handler.go 27 covered LOC · 3 ranges

Open complete file

64 clientBean client.Bean,
65 taskExecutorProvider TaskExecutorProvider,
66 > ) DLQHandler { dlq_handler.go
67 > return newDLQHandler(
68 > shard,
69 > deleteManager,
70 > workflowCache,
71 > clientBean,
72 > make(map[string]TaskExecutor),
73 > taskExecutorProvider,
74 > )
75 > }
76
77 func newDLQHandler(
82 taskExecutors map[string]TaskExecutor,
83 taskExecutorProvider TaskExecutorProvider,
84 > ) *dlqHandlerImpl { dlq_handler.go
85 >
86 > if taskExecutors == nil {
87 panic("Failed to initialize replication DLQ handler due to nil task executors")
88 }
89 > return &dlqHandlerImpl{ dlq_handler.go
90 > shard: shard,
91 > deleteManager: deleteManager,
92 > workflowCache: workflowCache,
93 > remoteHistoryFetcher: eventhandler.NewHistoryPaginatedFetcher(
94 > shard.GetNamespaceRegistry(),
95 > clientBean,
96 > shard.GetPayloadSerializer(),
97 > shard.GetLogger(),
98 > ),
99 > taskExecutors: taskExecutors,
100 > taskExecutorProvider: taskExecutorProvider,
101 > logger: shard.GetLogger(),
102 > }
103 }
104
go.temporal.io/server/service/history/shard/fx.go 27 covered LOC · 7 ranges

Open complete file

16 fx.Provide(
17 ControllerProvider,
18 > func(impl *ControllerImpl) Controller { return impl }, fx.go
19 ContextFactoryProvider,
20 NewDefaultHandoverTrackerFactory,
21 fx.Annotate(
22 > func(p Controller) pingable.Pingable { return p }, fx.go
23 fx.ResultTags(`group:"deadlockDetectorRoots"`),
24 ),
31 impl *ControllerImpl,
32 cfg *configs.Config,
33 > ) (*OwnershipBasedQuotaScalerImpl, error) { fx.go
34 > return NewOwnershipBasedQuotaScaler(
35 > impl,
36 > int(cfg.NumberOfShards),
37 > nil,
38 > )
39 > }),
40 fx.Provide(func(
41 impl *OwnershipBasedQuotaScalerImpl,
42 > ) OwnershipBasedQuotaScaler { fx.go
43 > return impl
44 > }),
45 > fx.Provide(func() LazyLoadedOwnershipBasedQuotaScaler {
46 > return LazyLoadedOwnershipBasedQuotaScaler{
47 > Value: &atomic.Value{},
48 > }
49 > }),
50 fx.Invoke(initLazyLoadedOwnershipBasedQuotaScaler),
51 fx.Invoke(func(
52 lc fx.Lifecycle,
53 impl *OwnershipBasedQuotaScalerImpl,
54 > ) { fx.go
55 > lc.Append(fx.Hook{
56 > OnStop: func(_ context.Context) error {
57 > impl.Close() fx.go
58 > return nil
59 > },
60 })
61 }),
67 ownershipBasedQuotaScaler OwnershipBasedQuotaScaler,
68 lazyLoadedOwnershipBasedQuotaScaler LazyLoadedOwnershipBasedQuotaScaler,
69 > ) { fx.go
70 > lazyLoadedOwnershipBasedQuotaScaler.Store(ownershipBasedQuotaScaler)
71 > logger.Info("Initialized lazy loaded OwnershipBasedQuotaScaler", tag.Service(serviceName))
72 > }
go.temporal.io/server/service/history/transfer_queue_active_task_executor.go 27 covered LOC · 1 range

Open complete file

74 versionCache worker_versioning.VersionMembershipAndReactivationStatusCache,
75 testHooks testhooks.TestHooks,
76 > ) queues.Executor { transfer_queue_active_task_executor.go
77 > return &transferQueueActiveTaskExecutor{
78 > transferQueueTaskExecutorBase: newTransferQueueTaskExecutorBase(
79 > shard,
80 > workflowCache,
81 > logger,
82 > metricProvider,
83 > historyRawClient,
84 > matchingRawClient,
85 > visibilityManager,
86 > chasmEngine,
87 > ),
88 > workflowResetter: ndc.NewWorkflowResetter(
89 > shard,
90 > workflowCache,
91 > logger,
92 > ),
93 > parentClosePolicyClient: parentclosepolicy.NewClient(
94 > shard.GetMetricsHandler(),
95 > shard.GetLogger(),
96 > sdkClientFactory,
97 > config.NumParentClosePolicySystemWorkflows(),
98 > ),
99 > versionCache: versionCache,
100 > testHooks: testHooks,
101 > }
102 > }
103
104 func (t *transferQueueActiveTaskExecutor) Execute(
go.temporal.io/server/temporal/cluster_metadata_loader.go 27 covered LOC · 8 ranges

Open complete file

20
21 // NewClusterMetadataLoader creates a new [ClusterMetadataLoader] that loads cluster metadata from the database.
22 > func NewClusterMetadataLoader(manager persistence.ClusterMetadataManager, logger log.Logger) *ClusterMetadataLoader { cluster_metadata_loader.go
23 > return &ClusterMetadataLoader{
24 > manager: manager,
25 > logger: logger,
26 > }
27 > }
28
29 // LoadAndMergeWithStaticConfig loads cluster metadata from the database and merges it with the static config.
30 > func (c *ClusterMetadataLoader) LoadAndMergeWithStaticConfig(ctx context.Context, svc *config.Config) error { cluster_metadata_loader.go
31 > iter := cluster.GetAllClustersIter(ctx, c.manager)
32 >
33 > for iter.HasNext() {
34 > item, err := iter.Next()
35 > if err != nil {
36 return err
37 }
38 > newMetadata := cluster.ClusterInformationFromDB(item) cluster_metadata_loader.go
39 > c.mergeMetadataFromDBWithStaticConfig(svc, item.ClusterName, newMetadata)
40 }
41 > return nil cluster_metadata_loader.go
42 }
43
44 > func (c *ClusterMetadataLoader) mergeMetadataFromDBWithStaticConfig(svc *config.Config, clusterName string, newMetadata *cluster.ClusterInformation) { cluster_metadata_loader.go
45 > c.backfillShardCount(svc, newMetadata)
46 > if currentMetadata, ok := svc.ClusterMetadata.ClusterInformation[clusterName]; ok {
47 > c.reconcileMetadata(svc, clusterName, currentMetadata, newMetadata)
48 > }
49 > svc.ClusterMetadata.ClusterInformation[clusterName] = *newMetadata
50 }
51
56 currentMetadata cluster.ClusterInformation,
57 newMetadata *cluster.ClusterInformation,
59 > if clusterName != svc.ClusterMetadata.CurrentClusterName {
60 c.logger.Warn(
61 "ClusterInformation in static config is deprecated. Please use TCTL tool to configure remote cluster connections",
65 return
66 }
67 > newMetadata.RPCAddress = currentMetadata.RPCAddress cluster_metadata_loader.go
68 > c.logger.Info(fmt.Sprintf("Use rpc address %v for cluster %v.", newMetadata.RPCAddress, clusterName))
69 }
70
71 // backfillShardCount is to add backward compatibility to the svc based cluster connection. It sets the shard count for
72 // newMetadata to the number of shards in the current cluster, if the shard count is not set in the database.
73 > func (c *ClusterMetadataLoader) backfillShardCount(svc *config.Config, newMetadata *cluster.ClusterInformation) { cluster_metadata_loader.go
74 > if newMetadata.ShardCount == 0 {
75 newMetadata.ShardCount = svc.Persistence.NumHistoryShards
76 }
go.temporal.io/server/temporal/server_option.go 27 covered LOC · 7 ranges

Open complete file

31 )
32
33 > func (f applyFunc) apply(s *serverOptions) { f(s) } server_option.go
34
35 // WithConfig sets a custom configuration
36 > func WithConfig(cfg *config.Config) ServerOption { server_option.go
37 > return applyFunc(func(s *serverOptions) {
38 > s.config = cfg
39 > })
40 }
41
55
56 // ForServices indicates which supplied services (e.g. frontend, history, matching, worker) within the server to start
57 > func ForServices(names []string) ServerOption { server_option.go
58 > return applyFunc(func(s *serverOptions) {
59 > s.serviceNames = make(map[primitives.ServiceName]struct{})
60 > for _, name := range names {
61 > s.serviceNames[primitives.ServiceName(name)] = struct{}{}
62 > }
63 })
64 }
82
83 // WithLogger sets a custom logger
84 > func WithLogger(logger log.Logger) ServerOption { server_option.go
85 > return applyFunc(func(s *serverOptions) {
86 > s.logger = logger
87 > })
88 }
89
96
97 // WithAuthorizer sets a low level authorizer to allow/deny all API calls
98 > func WithAuthorizer(authorizer authorization.Authorizer) ServerOption { server_option.go
99 > return applyFunc(func(s *serverOptions) {
100 > s.authorizer = authorizer
101 > })
102 }
103
110
111 // WithClaimMapper configures a role mapper for authorization
112 > func WithClaimMapper(claimMapper func(cfg *config.Config) authorization.ClaimMapper) ServerOption { server_option.go
113 > return applyFunc(func(s *serverOptions) {
114 > s.claimMapper = claimMapper(s.config)
115 > })
116 }
117
138
139 // WithDynamicConfigClient sets custom client for reading dynamic configuration.
140 > func WithDynamicConfigClient(c dynamicconfig.Client) ServerOption { server_option.go
141 > return applyFunc(func(s *serverOptions) {
142 > s.dynamicConfigClient = c
143 > })
144 }
145
go.temporal.io/server/api/enums/v1/common.pb.go 26 covered LOC · 4 ranges

Open complete file

120 }
121
122 > func (ChecksumFlavor) Descriptor() protoreflect.EnumDescriptor { common.pb.go
123 > return file_temporal_server_api_enums_v1_common_proto_enumTypes[1].Descriptor()
124 > }
125
126 func (ChecksumFlavor) Type() protoreflect.EnumType {
201 }
202
203 > func (CallbackState) Descriptor() protoreflect.EnumDescriptor { common.pb.go
204 > return file_temporal_server_api_enums_v1_common_proto_enumTypes[2].Descriptor()
205 > }
206
207 func (CallbackState) Type() protoreflect.EnumType {
264 }
265
266 > func init() { file_temporal_server_api_enums_v1_common_proto_init() } common.pb.go
267 > func file_temporal_server_api_enums_v1_common_proto_init() {
268 > if File_temporal_server_api_enums_v1_common_proto != nil {
269 return
270 }
271 > type x struct{} common.pb.go
272 > out := protoimpl.TypeBuilder{
273 > File: protoimpl.DescBuilder{
274 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
275 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_common_proto_rawDesc), len(file_temporal_server_api_enums_v1_common_proto_rawDesc)),
276 > NumEnums: 3,
277 > NumMessages: 0,
278 > NumExtensions: 0,
279 > NumServices: 0,
280 > },
281 > GoTypes: file_temporal_server_api_enums_v1_common_proto_goTypes,
282 > DependencyIndexes: file_temporal_server_api_enums_v1_common_proto_depIdxs,
283 > EnumInfos: file_temporal_server_api_enums_v1_common_proto_enumTypes,
284 > }.Build()
285 > File_temporal_server_api_enums_v1_common_proto = out.File
286 > file_temporal_server_api_enums_v1_common_proto_goTypes = nil
287 > file_temporal_server_api_enums_v1_common_proto_depIdxs = nil
288 }
go.temporal.io/server/api/enums/v1/task.pb.go 26 covered LOC · 4 ranges

Open complete file

303 }
304
305 > func (TaskType) Descriptor() protoreflect.EnumDescriptor { task.pb.go
306 > return file_temporal_server_api_enums_v1_task_proto_enumTypes[1].Descriptor()
307 > }
308
309 func (TaskType) Type() protoreflect.EnumType {
361 }
362
363 > func (TaskPriority) Descriptor() protoreflect.EnumDescriptor { task.pb.go
364 > return file_temporal_server_api_enums_v1_task_proto_enumTypes[2].Descriptor()
365 > }
366
367 func (TaskPriority) Type() protoreflect.EnumType {
456 }
457
458 > func init() { file_temporal_server_api_enums_v1_task_proto_init() } task.pb.go
459 > func file_temporal_server_api_enums_v1_task_proto_init() {
460 > if File_temporal_server_api_enums_v1_task_proto != nil {
461 return
462 }
463 > type x struct{} task.pb.go
464 > out := protoimpl.TypeBuilder{
465 > File: protoimpl.DescBuilder{
466 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
467 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_task_proto_rawDesc), len(file_temporal_server_api_enums_v1_task_proto_rawDesc)),
468 > NumEnums: 3,
469 > NumMessages: 0,
470 > NumExtensions: 0,
471 > NumServices: 0,
472 > },
473 > GoTypes: file_temporal_server_api_enums_v1_task_proto_goTypes,
474 > DependencyIndexes: file_temporal_server_api_enums_v1_task_proto_depIdxs,
475 > EnumInfos: file_temporal_server_api_enums_v1_task_proto_enumTypes,
476 > }.Build()
477 > File_temporal_server_api_enums_v1_task_proto = out.File
478 > file_temporal_server_api_enums_v1_task_proto_goTypes = nil
479 > file_temporal_server_api_enums_v1_task_proto_depIdxs = nil
480 }
go.temporal.io/server/api/enums/v1/workflow.pb.go 26 covered LOC · 4 ranges

Open complete file

86 }
87
88 > func (WorkflowExecutionState) Descriptor() protoreflect.EnumDescriptor { workflow.pb.go
89 > return file_temporal_server_api_enums_v1_workflow_proto_enumTypes[0].Descriptor()
90 > }
91
92 func (WorkflowExecutionState) Type() protoreflect.EnumType {
150 }
151
152 > func (WorkflowBackoffType) Descriptor() protoreflect.EnumDescriptor { workflow.pb.go
153 > return file_temporal_server_api_enums_v1_workflow_proto_enumTypes[1].Descriptor()
154 > }
155
156 func (WorkflowBackoffType) Type() protoreflect.EnumType {
275 }
276
277 > func init() { file_temporal_server_api_enums_v1_workflow_proto_init() } workflow.pb.go
278 > func file_temporal_server_api_enums_v1_workflow_proto_init() {
279 > if File_temporal_server_api_enums_v1_workflow_proto != nil {
280 return
281 }
282 > type x struct{} workflow.pb.go
283 > out := protoimpl.TypeBuilder{
284 > File: protoimpl.DescBuilder{
285 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
286 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_workflow_proto_rawDesc), len(file_temporal_server_api_enums_v1_workflow_proto_rawDesc)),
287 > NumEnums: 3,
288 > NumMessages: 0,
289 > NumExtensions: 0,
290 > NumServices: 0,
291 > },
292 > GoTypes: file_temporal_server_api_enums_v1_workflow_proto_goTypes,
293 > DependencyIndexes: file_temporal_server_api_enums_v1_workflow_proto_depIdxs,
294 > EnumInfos: file_temporal_server_api_enums_v1_workflow_proto_enumTypes,
295 > }.Build()
296 > File_temporal_server_api_enums_v1_workflow_proto = out.File
297 > file_temporal_server_api_enums_v1_workflow_proto_goTypes = nil
298 > file_temporal_server_api_enums_v1_workflow_proto_depIdxs = nil
299 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/message.pb.go 26 covered LOC · 1 range

Open complete file

843 }
844
845 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_init() } message.pb.go
846 > func file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_init() {
847 > if File_temporal_server_chasm_lib_scheduler_proto_v1_message_proto != nil {
848 > return
849 > }
850 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_msgTypes[4].OneofWrappers = []any{
851 > (*BackfillerState_BackfillRequest)(nil),
852 > (*BackfillerState_TriggerRequest)(nil),
853 > }
854 > type x struct{}
855 > out := protoimpl.TypeBuilder{
856 > File: protoimpl.DescBuilder{
857 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
858 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_rawDesc)),
859 > NumEnums: 0,
860 > NumMessages: 12,
861 > NumExtensions: 0,
862 > NumServices: 0,
863 > },
864 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_goTypes,
865 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_depIdxs,
866 > MessageInfos: file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_msgTypes,
867 > }.Build()
868 > File_temporal_server_chasm_lib_scheduler_proto_v1_message_proto = out.File
869 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_goTypes = nil
870 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_depIdxs = nil
871 }
go.temporal.io/server/client/matching/partition_cache.go 26 covered LOC · 5 ranges

Open complete file

37 func newPartitionCache(
38 metricsHandler metrics.Handler,
39 > ) *partitionCache { partition_cache.go
40 > return &partitionCache{
41 > metricsHandler: metricsHandler,
42 > }
43 > }
44
45 > func (c *partitionCache) Start() { partition_cache.go
46 > for i := range c.shards {
47 > c.shards[i].rotate()
48 > }
49 > c.rotate = goro.NewHandle(context.Background()).Go(func(ctx context.Context) error {
50 > t := time.NewTicker(partitionCacheRotateInterval / partitionCacheNumShards)
51 > defer t.Stop()
52 > for i := 0; ; i = (i + 1) % partitionCacheNumShards {
53 > select {
54 case <-t.C:
55 c.shards[i].rotate()
56 c.emitMetrics()
57 > case <-ctx.Done(): partition_cache.go
58 > return ctx.Err()
59 }
60 }
62 }
63
64 > func (c *partitionCache) Stop() { partition_cache.go
65 > c.rotate.Cancel()
66 > <-c.rotate.Done()
67 > }
68
69 func (c *partitionCache) emitMetrics() {
129 }
130
131 > func (s *partitionCacheShard) rotate() { partition_cache.go
132 > s.lock.Lock()
133 > defer s.lock.Unlock()
134 > s.prev = s.active
135 > s.active = make(map[string]PartitionCounts)
136 > }
137
138 func (s *partitionCacheShard) size() int {
go.temporal.io/server/common/rpc/interceptor/sdk_version.go 26 covered LOC · 4 ranges

Open complete file

20
21 // NewSDKVersionInterceptor creates a new SDKVersionInterceptor with default max set size
22 > func NewSDKVersionInterceptor() *SDKVersionInterceptor { sdk_version.go
23 > return &SDKVersionInterceptor{
24 > sdkInfoSet: make(map[versioninfo.SDKInfo]struct{}),
25 > versionChecker: headers.NewDefaultVersionChecker(),
26 > maxSetSize: defaultMaxSetSize,
27 > }
28 > }
29
30 // Intercept a grpc request
34 info *grpc.UnaryServerInfo,
35 handler grpc.UnaryHandler,
36 > ) (any, error) { sdk_version.go
37 > sdkName, sdkVersion := headers.GetClientNameAndVersion(ctx)
38 > if sdkName != "" && sdkVersion != "" {
39 > vi.RecordSDKInfo(sdkName, sdkVersion)
40 > if err := vi.versionChecker.ClientSupported(ctx); err != nil {
41 return nil, err
42 }
43 }
44 > return handler(ctx, req) sdk_version.go
45 }
46
47 // RecordSDKInfo records name and version tuple in memory
48 > func (vi *SDKVersionInterceptor) RecordSDKInfo(name, version string) { sdk_version.go
49 > info := versioninfo.SDKInfo{Name: name, Version: version}
50 >
51 > vi.RLock()
52 > overCap := len(vi.sdkInfoSet) >= vi.maxSetSize
53 > _, found := vi.sdkInfoSet[info]
54 > vi.RUnlock()
55 >
56 > if !overCap && !found {
57 > vi.Lock()
58 > vi.sdkInfoSet[info] = struct{}{}
59 > vi.Unlock()
60 > }
61 }
62
go.temporal.io/server/service/history/queues/scheduler_quotas.go 26 covered LOC · 8 ranges

Open complete file

13 persistenceNamespaceRateFn quotas.NamespaceRateFn,
14 persistenceHostRateFn quotas.RateFn,
15 > ) (SchedulerRateLimiter, error) { scheduler_quotas.go
16 >
17 > namespaceRateFnWithFallback := func(namespace string) float64 {
18 if rate := namespaceRateFn(namespace); rate > 0 {
19 return rate
23 }
24
25 > hostRateFnWithFallback := func() float64 { scheduler_quotas.go
26 > if rate := hostRateFn(); rate > 0 {
27 return rate
28 }
29
30 > return persistenceHostRateFn() scheduler_quotas.go
31 }
32
33 > requestPriorityFn := func(req quotas.Request) int { scheduler_quotas.go
34 // NOTE: task scheduler will use the string format for task priority as the caller type.
35 // see channelQuotaRequestFn in scheduler.go
43 }
44
45 > priorityToRateLimiters := make(map[int]quotas.RequestRateLimiter, len(tasks.PriorityName)) scheduler_quotas.go
46 > for priority := range tasks.PriorityName {
47 > priorityToRateLimiters[int(priority)] = newTaskRequestRateLimiter(
48 > namespaceRateFnWithFallback,
49 > hostRateFnWithFallback,
50 > )
51 > }
52
53 > priorityLimiter := quotas.NewPriorityRateLimiter(requestPriorityFn, priorityToRateLimiters) scheduler_quotas.go
54 >
55 > return priorityLimiter, nil
56 }
57
59 namespaceRateFn quotas.NamespaceRateFn,
60 hostRateFn quotas.RateFn,
61 > ) quotas.RequestRateLimiter { scheduler_quotas.go
62 > hostRequestRateLimiter := quotas.NewRequestRateLimiterAdapter(
63 > quotas.NewDefaultIncomingRateLimiter(hostRateFn),
64 > )
65 > namespaceRequestRateLimiterFn := func(req quotas.Request) quotas.RequestRateLimiter {
66 if len(req.Caller) == 0 {
67 return quotas.NoopRequestRateLimiter
81 }
82
83 > return quotas.NewMultiRequestRateLimiter( scheduler_quotas.go
84 > quotas.NewNamespaceRequestRateLimiter(namespaceRequestRateLimiterFn),
85 > hostRequestRateLimiter,
86 > )
87 }
go.temporal.io/server/service/history/shard/ownership_based_quota_calculator.go 26 covered LOC · 6 ranges

Open complete file

24 perInstanceQuota func() int,
25 globalQuota func() int,
26 > ) *OwnershipAwareQuotaCalculator { ownership_based_quota_calculator.go
27 > return &OwnershipAwareQuotaCalculator{
28 > ClusterAwareQuotaCalculator: calculator.ClusterAwareQuotaCalculator{
29 > MemberCounter: memberCounter,
30 > PerInstanceQuota: perInstanceQuota,
31 > GlobalQuota: globalQuota,
32 > },
33 > scaler: scaler,
34 > }
35 > }
36
37 > func (c *OwnershipAwareQuotaCalculator) GetQuota() float64 { ownership_based_quota_calculator.go
38 > if quota, ok := getOwnershipScaledQuota(c.scaler, c.GlobalQuota()); ok {
39 return quota
40 }
41 > return c.ClusterAwareQuotaCalculator.GetQuota() ownership_based_quota_calculator.go
42 }
43
47 perInstanceQuota func(namespace string) int,
48 globalQuota func(namespace string) int,
49 > ) *OwnershipAwareNamespaceQuotaCalculator { ownership_based_quota_calculator.go
50 > return &OwnershipAwareNamespaceQuotaCalculator{
51 > ClusterAwareNamespaceQuotaCalculator: calculator.ClusterAwareNamespaceQuotaCalculator{
52 > MemberCounter: memberCounter,
53 > PerInstanceQuota: perInstanceQuota,
54 > GlobalQuota: globalQuota,
55 > },
56 > scaler: scaler,
57 > }
58 > }
59
60 func (c *OwnershipAwareNamespaceQuotaCalculator) GetQuota(namespace string) float64 {
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/activity_state.pb.go 25 covered LOC · 2 ranges

Open complete file

1382 }
1383
1384 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_init() } activity_state.pb.go
1385 > func file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_init() {
1386 > if File_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto != nil {
1387 return
1388 }
1389 > file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_msgTypes[7].OneofWrappers = []any{ activity_state.pb.go
1390 > (*ActivityOutcome_Successful_)(nil),
1391 > (*ActivityOutcome_Failed_)(nil),
1392 > }
1393 > type x struct{}
1394 > out := protoimpl.TypeBuilder{
1395 > File: protoimpl.DescBuilder{
1396 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1397 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_rawDesc)),
1398 > NumEnums: 2,
1399 > NumMessages: 11,
1400 > NumExtensions: 0,
1401 > NumServices: 0,
1402 > },
1403 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_goTypes,
1404 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_depIdxs,
1405 > EnumInfos: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_enumTypes,
1406 > MessageInfos: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_msgTypes,
1407 > }.Build()
1408 > File_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto = out.File
1409 > file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_goTypes = nil
1410 > file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_depIdxs = nil
1411 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/operation.pb.go 25 covered LOC · 2 ranges

Open complete file

998 }
999
1000 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_init() } operation.pb.go
1001 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_init() {
1002 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto != nil {
1003 return
1004 }
1005 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_msgTypes[2].OneofWrappers = []any{ operation.pb.go
1006 > (*OperationOutcome_Successful_)(nil),
1007 > (*OperationOutcome_Failed_)(nil),
1008 > }
1009 > type x struct{}
1010 > out := protoimpl.TypeBuilder{
1011 > File: protoimpl.DescBuilder{
1012 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1013 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_rawDesc)),
1014 > NumEnums: 2,
1015 > NumMessages: 8,
1016 > NumExtensions: 0,
1017 > NumServices: 0,
1018 > },
1019 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_goTypes,
1020 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_depIdxs,
1021 > EnumInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_enumTypes,
1022 > MessageInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_msgTypes,
1023 > }.Build()
1024 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto = out.File
1025 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_goTypes = nil
1026 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_depIdxs = nil
1027 }
go.temporal.io/server/client/matching/metric_client.go 25 covered LOC · 7 ranges

Open complete file

33 logger log.Logger,
34 throttledLogger log.Logger,
35 > ) matchingservice.MatchingServiceClient { metric_client.go
36 > return &metricClient{
37 > client: client,
38 > metricsHandler: metricsHandler,
39 > logger: logger,
40 > throttledLogger: throttledLogger,
41 > }
42 > }
43
44 func (c *metricClient) AddActivityTask(
212 ctx context.Context,
213 operation string,
214 > ) (metrics.Handler, time.Time) { metric_client.go
215 > caller := headers.GetCallerInfo(ctx).CallerName
216 > handler := c.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.NamespaceTag(caller), metrics.ServiceRoleTag(metrics.MatchingRoleTagValue))
217 > metrics.ClientRequests.With(handler).Record(1)
218 > return handler, time.Now().UTC()
219 > }
220
221 func (c *metricClient) finishMetricsRecording(
223 startTime time.Time,
224 err error,
225 > ) { metric_client.go
226 > if err != nil {
227 > switch err.(type) {
228 case *serviceerrors.StickyWorkerUnavailable,
229 *serviceerror.Canceled,
236 *serviceerror.ResourceExhausted:
237 // noop - not interest and too many logs
238 > default: metric_client.go
239 > c.throttledLogger.Info("matching client encountered error", tag.Error(err), tag.ServiceErrorType(err))
240 }
241 > metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) metric_client.go
242 }
243 > metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) metric_client.go
244 }
245
257 // Stop forwards a deterministic shutdown to the wrapped client. See
258 // clientImpl.Stop. It is only invoked via client.Bean.Close.
259 > func (c *metricClient) Stop() { metric_client.go
260 > if s, ok := c.client.(interface{ Stop() }); ok {
261 > s.Stop()
262 > }
263 }
go.temporal.io/server/common/membership/grpc_resolver.go 25 covered LOC · 9 ranges

Open complete file

53 )
54
55 > func init() { grpc_resolver.go
56 > // This must be called in init to avoid race conditions.
57 > resolver.Register(&globalGrpcBuilder)
58 > }
59
60 // Most code should not use this, this is only exposed for code that has to recognize and use a
61 // grpc membership url outside of grpc.
62 > func GetServiceResolverFromURL(u *url.URL) (ServiceResolver, error) { grpc_resolver.go
63 > return globalGrpcBuilder.getServiceResolver(u)
64 > }
65
66 // This should only be used in unit tests. For normal code, use the *GRPCResolver provided by fx.
70 }
71
72 > func newGRPCResolver(monitor Monitor) *GRPCResolver { grpc_resolver.go
73 > res := &GRPCResolver{monitor: monitor}
74 > globalGrpcBuilder.resolvers.Store(fmt.Sprintf("%p", res), res)
75 > return res
76 > }
77
78 > func (g *GRPCResolver) MakeURL(service primitives.ServiceName) string { grpc_resolver.go
79 > return fmt.Sprintf("%s://%s%s%p", grpcResolverScheme, string(service), delim, g)
80 > }
81
82 > func (m *grpcBuilder) Scheme() string { grpc_resolver.go
83 > return grpcResolverScheme
84 > }
85
86 > func (m *grpcBuilder) getServiceResolver(u *url.URL) (ServiceResolver, error) { grpc_resolver.go
87 > if u.Scheme != grpcResolverScheme {
88 return nil, errInvalidUrl
89 }
90 > service, ptr, found := strings.Cut(u.Host, delim) grpc_resolver.go
91 > if !found {
92 return nil, errInvalidUrl
93 }
94 > v, ok := m.resolvers.Load(ptr) grpc_resolver.go
95 > if !ok {
96 return nil, errNotInitialized
97 }
98 > return v.(*GRPCResolver).monitor.GetResolver(primitives.ServiceName(service)) grpc_resolver.go
99 }
100
go.temporal.io/server/common/metrics/grpc_stats.go 25 covered LOC · 7 ranges

Open complete file

17 }
18
19 > func NewServerStatsHandler(mh Handler) ServerStatsHandler { grpc_stats.go
20 > return &grpcStatsHandler{
21 > mh: mh,
22 > }
23 > }
24
25 > func (h *grpcStatsHandler) TagConn(ctx context.Context, _ *stats.ConnTagInfo) context.Context { grpc_stats.go
26 > return ctx
27 > }
28
29 > func (h *grpcStatsHandler) HandleConn(_ context.Context, stat stats.ConnStats) { grpc_stats.go
30 > switch stat.(type) {
31 > case *stats.ConnBegin:
32 > ServiceConnAccepted.With(h.mh).Record(1)
33 > newVal := h.activeConns.Add(1)
34 > ServiceConnActive.With(h.mh).Record(float64(newVal))
35 > case *stats.ConnEnd: grpc_stats.go
36 > ServiceConnClosed.With(h.mh).Record(1)
37 > newVal := h.activeConns.Add(-1)
38 > if newVal < 0 { // should never happen, but just in case
39 h.activeConns.Store(0)
40 newVal = 0
41 }
42 > ServiceConnActive.With(h.mh).Record(float64(newVal)) grpc_stats.go
43 }
44 }
45
46 > func (h *grpcStatsHandler) TagRPC(ctx context.Context, _ *stats.RPCTagInfo) context.Context { grpc_stats.go
47 > return ctx
48 > }
49
50 > func (h *grpcStatsHandler) HandleRPC(ctx context.Context, stat stats.RPCStats) { grpc_stats.go
51 > // nothing to do here
52 > }
go.temporal.io/server/common/persistence/dlq_metrics_emitter.go 25 covered LOC · 7 ranges

Open complete file

43 hostInfoProvider membership.HostInfoProvider,
44 taskCategoryRegistry tasks.TaskCategoryRegistry,
45 > ) *DLQMetricsEmitter { dlq_metrics_emitter.go
46 > return &DLQMetricsEmitter{
47 > status: common.DaemonStatusInitialized,
48 > shutdownCh: make(chan struct{}),
49 > metricsHandler: metricsHandler,
50 > emitMetricsTimer: time.NewTicker(emitDLQMetricsInterval),
51 > logger: logger,
52 > historyTaskQueueManager: manager,
53 > historyServiceResolver: historyServiceResolver,
54 > hostInfoProvider: hostInfoProvider,
55 > taskCategoryRegistry: taskCategoryRegistry,
56 > }
57 > }
58
59 > func (s *DLQMetricsEmitter) Start() { dlq_metrics_emitter.go
60 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
61 return
62 }
63 > go s.emitMetricsLoop() dlq_metrics_emitter.go
64 }
65
66 > func (s *DLQMetricsEmitter) Stop() { dlq_metrics_emitter.go
67 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
68 return
69 }
70 > close(s.shutdownCh) dlq_metrics_emitter.go
71 > s.emitMetricsTimer.Stop()
72 }
73
74 > func (s *DLQMetricsEmitter) emitMetricsLoop() { dlq_metrics_emitter.go
75 > for {
76 > select {
77 > case <-s.shutdownCh: dlq_metrics_emitter.go
78 > return
79 case <-s.emitMetricsTimer.C:
80 if s.shouldEmitMetrics() {
go.temporal.io/server/common/persistence/sql/nexus_endpoint_store.go 25 covered LOC · 10 ranges

Open complete file

34 logger log.Logger,
35 serializer serialization.Serializer,
36 > ) (p.NexusEndpointStore, error) { nexus_endpoint_store.go
37 > return &sqlNexusEndpointStore{
38 > SqlStore: NewSQLStore(db, logger, serializer),
39 > }, nil
40 > }
41
42 func (s *sqlNexusEndpointStore) CreateOrUpdateNexusEndpoint(
118 ctx context.Context,
119 request *p.ListNexusEndpointsRequest,
120 > ) (*p.InternalListNexusEndpointsResponse, error) { nexus_endpoint_store.go
121 > lastID := emptyID
122 > if len(request.NextPageToken) > 0 {
123 token, err := deserializePageTokenJson[listEndpointsNextPageToken](request.NextPageToken)
124 if err != nil {
128 }
129
130 > var response p.InternalListNexusEndpointsResponse nexus_endpoint_store.go
131 > var rows []sqlplugin.NexusEndpointsRow
132 > retErr := s.txExecute(ctx, "ListNexusEndpoints", func(tx sqlplugin.Tx) error {
133 > curTableVersion, err := tx.GetNexusEndpointsTableVersion(ctx)
134 > if err != nil {
135 return err
136 }
137 > response.TableVersion = curTableVersion nexus_endpoint_store.go
138 > if request.LastKnownTableVersion != 0 && request.LastKnownTableVersion != curTableVersion {
139 return p.ErrNexusTableVersionConflict
140 }
141
142 > if request.PageSize > 0 { nexus_endpoint_store.go
143 // PageSize could be zero when fetching just the table version.
144 rows, err = tx.ListNexusEndpoints(ctx, &sqlplugin.ListNexusEndpointsRequest{
148 }
149
150 > return err nexus_endpoint_store.go
151 })
152
153 > if retErr != nil { nexus_endpoint_store.go
154 return &response, retErr
155 }
156
157 > var nextPageToken []byte nexus_endpoint_store.go
158 > if len(rows) > 0 && len(rows) == request.PageSize {
159 // len(rows) could be zero when fetching just the table version.
160 nextPageToken, retErr = serializePageTokenJson(&listEndpointsNextPageToken{
166 }
167 }
168 > response.NextPageToken = nextPageToken nexus_endpoint_store.go
169 >
170 > response.Endpoints = make([]p.InternalNexusEndpoint, len(rows))
171 > for i, row := range rows {
172 response.Endpoints[i].ID = primitives.UUIDString(row.ID)
173 response.Endpoints[i].Version = row.Version
go.temporal.io/server/common/tasks/execution_queue_scheduler.go 25 covered LOC · 6 ranges

Open complete file

71 metricsHandler metrics.Handler,
72 timeSource clock.TimeSource,
73 > ) *executionQueueScheduler[T] { execution_queue_scheduler.go
74 > s := &executionQueueScheduler[T]{
75 > shutdownChan: make(chan struct{}),
76 > maxQueues: maxQueues,
77 > queueTTL: queueTTL,
78 > queueConcurrency: queueConcurrency,
79 > queueKeyFn: queueKeyFn,
80 > logger: logger,
81 > metricsHandler: metricsHandler,
82 > timeSource: timeSource,
83 > queues: make(map[any]*executionQueue[T]),
84 > }
85 > s.status.Store(common.DaemonStatusInitialized)
86 > return s
87 > }
88
89 > func (s *executionQueueScheduler[T]) Start() { execution_queue_scheduler.go
90 > if !s.status.CompareAndSwap(common.DaemonStatusInitialized, common.DaemonStatusStarted) {
91 return
92 }
93 > s.logger.Info("execution queue scheduler started") execution_queue_scheduler.go
94 }
95
96 > func (s *executionQueueScheduler[T]) Stop() { execution_queue_scheduler.go
97 > if !s.status.CompareAndSwap(common.DaemonStatusStarted, common.DaemonStatusStopped) {
98 return
99 }
100
101 > close(s.shutdownChan) execution_queue_scheduler.go
102 >
103 > go func() {
104 > if success := common.AwaitWaitGroup(&s.shutdownWG, time.Minute); !success {
105 s.logger.Warn("execution queue scheduler timed out waiting for goroutines")
106 }
107 }()
108
109 > s.logger.Info("execution queue scheduler stopped") execution_queue_scheduler.go
110 }
111
go.temporal.io/server/api/clock/v1/message.pb.go 24 covered LOC · 4 ranges

Open complete file

45 func (*VectorClock) ProtoMessage() {}
46
47 > func (x *VectorClock) ProtoReflect() protoreflect.Message { message.pb.go
48 > mi := &file_temporal_server_api_clock_v1_message_proto_msgTypes[0]
49 > if x != nil {
50 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
51 if ms.LoadMessageInfo() == nil {
54 return ms
55 }
56 > return mi.MessageOf(x) message.pb.go
57 }
58
193 }
194
195 > func init() { file_temporal_server_api_clock_v1_message_proto_init() } message.pb.go
196 > func file_temporal_server_api_clock_v1_message_proto_init() {
197 > if File_temporal_server_api_clock_v1_message_proto != nil {
198 return
199 }
200 > type x struct{} message.pb.go
201 > out := protoimpl.TypeBuilder{
202 > File: protoimpl.DescBuilder{
203 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
204 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_clock_v1_message_proto_rawDesc), len(file_temporal_server_api_clock_v1_message_proto_rawDesc)),
205 > NumEnums: 0,
206 > NumMessages: 2,
207 > NumExtensions: 0,
208 > NumServices: 0,
209 > },
210 > GoTypes: file_temporal_server_api_clock_v1_message_proto_goTypes,
211 > DependencyIndexes: file_temporal_server_api_clock_v1_message_proto_depIdxs,
212 > MessageInfos: file_temporal_server_api_clock_v1_message_proto_msgTypes,
213 > }.Build()
214 > File_temporal_server_api_clock_v1_message_proto = out.File
215 > file_temporal_server_api_clock_v1_message_proto_goTypes = nil
216 > file_temporal_server_api_clock_v1_message_proto_depIdxs = nil
217 }
go.temporal.io/server/api/persistence/v1/nexus.pb.go 24 covered LOC · 2 ranges

Open complete file

481 }
482
483 > func init() { file_temporal_server_api_persistence_v1_nexus_proto_init() } nexus.pb.go
484 > func file_temporal_server_api_persistence_v1_nexus_proto_init() {
485 > if File_temporal_server_api_persistence_v1_nexus_proto != nil {
486 return
487 }
488 > file_temporal_server_api_persistence_v1_nexus_proto_msgTypes[1].OneofWrappers = []any{ nexus.pb.go
489 > (*NexusEndpointTarget_Worker_)(nil),
490 > (*NexusEndpointTarget_External_)(nil),
491 > }
492 > type x struct{}
493 > out := protoimpl.TypeBuilder{
494 > File: protoimpl.DescBuilder{
495 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
496 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_nexus_proto_rawDesc), len(file_temporal_server_api_persistence_v1_nexus_proto_rawDesc)),
497 > NumEnums: 0,
498 > NumMessages: 6,
499 > NumExtensions: 0,
500 > NumServices: 0,
501 > },
502 > GoTypes: file_temporal_server_api_persistence_v1_nexus_proto_goTypes,
503 > DependencyIndexes: file_temporal_server_api_persistence_v1_nexus_proto_depIdxs,
504 > MessageInfos: file_temporal_server_api_persistence_v1_nexus_proto_msgTypes,
505 > }.Build()
506 > File_temporal_server_api_persistence_v1_nexus_proto = out.File
507 > file_temporal_server_api_persistence_v1_nexus_proto_goTypes = nil
508 > file_temporal_server_api_persistence_v1_nexus_proto_depIdxs = nil
509 }
go.temporal.io/server/api/persistence/v1/workflow_mutable_state.pb.go 24 covered LOC · 2 ranges

Open complete file

532 }
533
534 > func init() { file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_init() } workflow_mutable_state.pb.go
535 > func file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_init() {
536 > if File_temporal_server_api_persistence_v1_workflow_mutable_state_proto != nil {
537 return
538 }
539 > file_temporal_server_api_persistence_v1_chasm_proto_init() workflow_mutable_state.pb.go
540 > file_temporal_server_api_persistence_v1_executions_proto_init()
541 > file_temporal_server_api_persistence_v1_hsm_proto_init()
542 > file_temporal_server_api_persistence_v1_update_proto_init()
543 > type x struct{}
544 > out := protoimpl.TypeBuilder{
545 > File: protoimpl.DescBuilder{
546 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
547 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_rawDesc), len(file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_rawDesc)),
548 > NumEnums: 0,
549 > NumMessages: 16,
550 > NumExtensions: 0,
551 > NumServices: 0,
552 > },
553 > GoTypes: file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_goTypes,
554 > DependencyIndexes: file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_depIdxs,
555 > MessageInfos: file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_msgTypes,
556 > }.Build()
557 > File_temporal_server_api_persistence_v1_workflow_mutable_state_proto = out.File
558 > file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_goTypes = nil
559 > file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_depIdxs = nil
560 }
go.temporal.io/server/api/schedule/v1/message.pb.go 24 covered LOC · 2 ranges

Open complete file

1224 }
1225
1226 > func init() { file_temporal_server_api_schedule_v1_message_proto_init() } message.pb.go
1227 > func file_temporal_server_api_schedule_v1_message_proto_init() {
1228 > if File_temporal_server_api_schedule_v1_message_proto != nil {
1229 return
1230 }
1231 > file_temporal_server_api_schedule_v1_message_proto_msgTypes[7].OneofWrappers = []any{ message.pb.go
1232 > (*WatchWorkflowResponse_Result)(nil),
1233 > (*WatchWorkflowResponse_Failure)(nil),
1234 > }
1235 > type x struct{}
1236 > out := protoimpl.TypeBuilder{
1237 > File: protoimpl.DescBuilder{
1238 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1239 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_schedule_v1_message_proto_rawDesc), len(file_temporal_server_api_schedule_v1_message_proto_rawDesc)),
1240 > NumEnums: 0,
1241 > NumMessages: 13,
1242 > NumExtensions: 0,
1243 > NumServices: 0,
1244 > },
1245 > GoTypes: file_temporal_server_api_schedule_v1_message_proto_goTypes,
1246 > DependencyIndexes: file_temporal_server_api_schedule_v1_message_proto_depIdxs,
1247 > MessageInfos: file_temporal_server_api_schedule_v1_message_proto_msgTypes,
1248 > }.Build()
1249 > File_temporal_server_api_schedule_v1_message_proto = out.File
1250 > file_temporal_server_api_schedule_v1_message_proto_goTypes = nil
1251 > file_temporal_server_api_schedule_v1_message_proto_depIdxs = nil
1252 }
go.temporal.io/server/api/workflow/v1/message.pb.go 24 covered LOC · 4 ranges

Open complete file

189 func (*BaseExecutionInfo) ProtoMessage() {}
190
191 > func (x *BaseExecutionInfo) ProtoReflect() protoreflect.Message { message.pb.go
192 > mi := &file_temporal_server_api_workflow_v1_message_proto_msgTypes[2]
193 > if x != nil {
194 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
195 if ms.LoadMessageInfo() == nil {
198 return ms
199 }
200 > return mi.MessageOf(x) message.pb.go
201 }
202
278 }
279
280 > func init() { file_temporal_server_api_workflow_v1_message_proto_init() } message.pb.go
281 > func file_temporal_server_api_workflow_v1_message_proto_init() {
282 > if File_temporal_server_api_workflow_v1_message_proto != nil {
283 return
284 }
285 > type x struct{} message.pb.go
286 > out := protoimpl.TypeBuilder{
287 > File: protoimpl.DescBuilder{
288 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
289 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_workflow_v1_message_proto_rawDesc), len(file_temporal_server_api_workflow_v1_message_proto_rawDesc)),
290 > NumEnums: 0,
291 > NumMessages: 3,
292 > NumExtensions: 0,
293 > NumServices: 0,
294 > },
295 > GoTypes: file_temporal_server_api_workflow_v1_message_proto_goTypes,
296 > DependencyIndexes: file_temporal_server_api_workflow_v1_message_proto_depIdxs,
297 > MessageInfos: file_temporal_server_api_workflow_v1_message_proto_msgTypes,
298 > }.Build()
299 > File_temporal_server_api_workflow_v1_message_proto = out.File
300 > file_temporal_server_api_workflow_v1_message_proto_goTypes = nil
301 > file_temporal_server_api_workflow_v1_message_proto_depIdxs = nil
302 }
go.temporal.io/server/chasm/lib/callback/gen/callbackpb/v1/message.pb.go 24 covered LOC · 2 ranges

Open complete file

462 }
463
464 > func init() { file_temporal_server_chasm_lib_callback_proto_v1_message_proto_init() } message.pb.go
465 > func file_temporal_server_chasm_lib_callback_proto_v1_message_proto_init() {
466 > if File_temporal_server_chasm_lib_callback_proto_v1_message_proto != nil {
467 return
468 }
469 > file_temporal_server_chasm_lib_callback_proto_v1_message_proto_msgTypes[1].OneofWrappers = []any{ message.pb.go
470 > (*Callback_Nexus_)(nil),
471 > }
472 > type x struct{}
473 > out := protoimpl.TypeBuilder{
474 > File: protoimpl.DescBuilder{
475 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
476 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_callback_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_callback_proto_v1_message_proto_rawDesc)),
477 > NumEnums: 1,
478 > NumMessages: 5,
479 > NumExtensions: 0,
480 > NumServices: 0,
481 > },
482 > GoTypes: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_goTypes,
483 > DependencyIndexes: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_depIdxs,
484 > EnumInfos: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_enumTypes,
485 > MessageInfos: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_msgTypes,
486 > }.Build()
487 > File_temporal_server_chasm_lib_callback_proto_v1_message_proto = out.File
488 > file_temporal_server_chasm_lib_callback_proto_v1_message_proto_goTypes = nil
489 > file_temporal_server_chasm_lib_callback_proto_v1_message_proto_depIdxs = nil
490 }
go.temporal.io/server/common/headers/caller_info.go 24 covered LOC · 4 ranges

Open complete file

79 func NewBackgroundHighCallerInfo(
80 callerName string,
81 > ) CallerInfo { caller_info.go
82 > return CallerInfo{
83 > CallerName: callerName,
84 > CallerType: CallerTypeBackgroundHigh,
85 > }
86 > }
87
88 // NewBackgroundLowCallerInfo creates a new CallerInfo with BackgroundLow callerType
117 ctx context.Context,
118 info CallerInfo,
119 > ) context.Context { caller_info.go
120 > return setIncomingMD(ctx, map[string]string{
121 > CallerNameHeaderName: info.CallerName,
122 > CallerTypeHeaderName: info.CallerType,
123 > CallOriginHeaderName: info.CallOrigin,
124 > })
125 > }
126
127 // SetCallerName set caller name in the context.
139 ctx context.Context,
140 callerType string,
141 > ) context.Context { caller_info.go
142 > return setIncomingMD(ctx, map[string]string{CallerTypeHeaderName: callerType})
143 > }
144
145 // SetOrigin set call origin in the context.
156 func GetCallerInfo(
157 ctx context.Context,
158 > ) CallerInfo { caller_info.go
159 > values := GetValues(ctx, CallerNameHeaderName, CallerTypeHeaderName, CallOriginHeaderName)
160 > return CallerInfo{
161 > CallerName: values[0],
162 > CallerType: values[1],
163 > CallOrigin: values[2],
164 > }
165 > }
go.temporal.io/server/common/namespace/replication_resolver.go 24 covered LOC · 5 ranges

Open complete file

49 }
50
51 > func NewDefaultReplicationResolverFactory() ReplicationResolverFactory { replication_resolver.go
52 > return func(detail *persistencespb.NamespaceDetail) ReplicationResolver {
53 > // By convention, a namespace with non-zero failover version is a global namespace
54 > // This can be overridden by WithGlobalFlag mutation if needed
55 > isGlobal := detail.FailoverVersion != 0
56 > return &defaultReplicationResolver{
57 > replicationConfig: detail.ReplicationConfig,
58 > isGlobalNamespace: isGlobal,
59 > failoverVersion: detail.FailoverVersion,
60 > failoverNotificationVersion: detail.FailoverNotificationVersion,
61 > }
62 > }
63 }
64
70 }
71
72 > func (r *defaultReplicationResolver) ActiveInCluster(clusterName string) bool { replication_resolver.go
73 > if !r.IsGlobalNamespace() {
74 > // namespace is not a global namespace, meaning namespace is always replication_resolver.go
75 > // "active" within each cluster
76 > return true
77 > }
78 return r.replicationConfig.ActiveClusterName == clusterName
79 }
96 }
97
98 > func (r *defaultReplicationResolver) IsGlobalNamespace() bool { replication_resolver.go
99 > return r.isGlobalNamespace
100 > }
101
102 func (r *defaultReplicationResolver) FailoverVersion(businessID string) int64 {
112 }
113
114 > func (r *defaultReplicationResolver) SetGlobalFlag(isGlobal bool) { replication_resolver.go
115 > r.isGlobalNamespace = isGlobal
116 > }
117
118 func (r *defaultReplicationResolver) SetActiveCluster(clusterName string) {
go.temporal.io/server/common/persistence/nexus_endpoint_manager.go 24 covered LOC · 6 ranges

Open complete file

32 serializer serialization.Serializer,
33 logger log.Logger,
34 > ) NexusEndpointManager { nexus_endpoint_manager.go
35 > return &nexusEndpointManagerImpl{
36 > persistence: persistence,
37 > serializer: serializer,
38 > logger: logger,
39 > }
40 > }
41
42 func (m *nexusEndpointManagerImpl) GetName() string {
44 }
45
46 > func (m *nexusEndpointManagerImpl) Close() { nexus_endpoint_manager.go
47 > m.persistence.Close()
48 > }
49
50 func (m *nexusEndpointManagerImpl) GetNexusEndpoint(
73 ctx context.Context,
74 request *ListNexusEndpointsRequest,
75 > ) (*ListNexusEndpointsResponse, error) { nexus_endpoint_manager.go
76 > if request.PageSize < 0 {
77 return nil, ErrNegativeListNexusEndpointsPageSize
78 }
79
80 > result := &ListNexusEndpointsResponse{} nexus_endpoint_manager.go
81 >
82 > resp, err := m.persistence.ListNexusEndpoints(ctx, request)
83 > if resp != nil {
84 > result.TableVersion = resp.TableVersion
85 > }
86 > if err != nil {
87 return result, err
88 }
89
90 > entries := make([]*persistencespb.NexusEndpointEntry, len(resp.Endpoints)) nexus_endpoint_manager.go
91 > for i, entry := range resp.Endpoints {
92 endpoint, err := m.serializer.NexusEndpointFromBlob(entry.Data)
93 if err != nil {
102 }
103
104 > result.NextPageToken = resp.NextPageToken nexus_endpoint_manager.go
105 > result.Entries = entries
106 > return result, nil
107 }
108
go.temporal.io/server/common/sdk/metrics_handler.go 24 covered LOC · 8 ranges

Open complete file

31 var _ sdkclient.MetricsHandler = &MetricsHandler{}
32
33 > func NewMetricsHandler(provider metrics.Handler) *MetricsHandler { metrics_handler.go
34 > return &MetricsHandler{provider: provider}
35 > }
36
37 > func (m *MetricsHandler) WithTags(tags map[string]string) sdkclient.MetricsHandler { metrics_handler.go
38 > t := make([]metrics.Tag, 0, len(tags))
39 > for k, v := range tags {
40 > t = append(t, metrics.StringTag(k, v))
41 > }
42
43 > return NewMetricsHandler(m.provider.WithTags(t...)) metrics_handler.go
44 }
45
46 > func (m *MetricsHandler) Counter(name string) sdkclient.MetricsCounter { metrics_handler.go
47 > return &metricsCounter{name: name, provider: m.provider}
48 > }
49
50 > func (m *MetricsHandler) Gauge(name string) sdkclient.MetricsGauge { metrics_handler.go
51 > return &metricsGauge{name: name, provider: m.provider}
52 > }
53
54 > func (m *MetricsHandler) Timer(name string) sdkclient.MetricsTimer { metrics_handler.go
55 > return &metricsTimer{name: name, provider: m.provider}
56 > }
57
58 > func (m metricsCounter) Inc(i int64) { metrics_handler.go
59 > m.provider.Counter(m.name).Record(i)
60 > }
61
62 func (m metricsGauge) Update(f float64) {
64 }
65
66 > func (m metricsTimer) Record(duration time.Duration) { metrics_handler.go
67 > m.provider.Timer(m.name).Record(duration)
68 > }
go.temporal.io/server/api/enums/v1/nexus.pb.go 23 covered LOC · 3 ranges

Open complete file

102 }
103
104 > func (NexusOperationState) Descriptor() protoreflect.EnumDescriptor { nexus.pb.go
105 > return file_temporal_server_api_enums_v1_nexus_proto_enumTypes[0].Descriptor()
106 > }
107
108 func (NexusOperationState) Type() protoreflect.EnumType {
158 }
159
160 > func init() { file_temporal_server_api_enums_v1_nexus_proto_init() } nexus.pb.go
161 > func file_temporal_server_api_enums_v1_nexus_proto_init() {
162 > if File_temporal_server_api_enums_v1_nexus_proto != nil {
163 return
164 }
165 > type x struct{} nexus.pb.go
166 > out := protoimpl.TypeBuilder{
167 > File: protoimpl.DescBuilder{
168 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
169 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_nexus_proto_rawDesc), len(file_temporal_server_api_enums_v1_nexus_proto_rawDesc)),
170 > NumEnums: 1,
171 > NumMessages: 0,
172 > NumExtensions: 0,
173 > NumServices: 0,
174 > },
175 > GoTypes: file_temporal_server_api_enums_v1_nexus_proto_goTypes,
176 > DependencyIndexes: file_temporal_server_api_enums_v1_nexus_proto_depIdxs,
177 > EnumInfos: file_temporal_server_api_enums_v1_nexus_proto_enumTypes,
178 > }.Build()
179 > File_temporal_server_api_enums_v1_nexus_proto = out.File
180 > file_temporal_server_api_enums_v1_nexus_proto_goTypes = nil
181 > file_temporal_server_api_enums_v1_nexus_proto_depIdxs = nil
182 }
go.temporal.io/server/api/enums/v1/predicate.pb.go 23 covered LOC · 3 ranges

Open complete file

111 }
112
113 > func (PredicateType) Descriptor() protoreflect.EnumDescriptor { predicate.pb.go
114 > return file_temporal_server_api_enums_v1_predicate_proto_enumTypes[0].Descriptor()
115 > }
116
117 func (PredicateType) Type() protoreflect.EnumType {
170 }
171
172 > func init() { file_temporal_server_api_enums_v1_predicate_proto_init() } predicate.pb.go
173 > func file_temporal_server_api_enums_v1_predicate_proto_init() {
174 > if File_temporal_server_api_enums_v1_predicate_proto != nil {
175 return
176 }
177 > type x struct{} predicate.pb.go
178 > out := protoimpl.TypeBuilder{
179 > File: protoimpl.DescBuilder{
180 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
181 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_predicate_proto_rawDesc), len(file_temporal_server_api_enums_v1_predicate_proto_rawDesc)),
182 > NumEnums: 1,
183 > NumMessages: 0,
184 > NumExtensions: 0,
185 > NumServices: 0,
186 > },
187 > GoTypes: file_temporal_server_api_enums_v1_predicate_proto_goTypes,
188 > DependencyIndexes: file_temporal_server_api_enums_v1_predicate_proto_depIdxs,
189 > EnumInfos: file_temporal_server_api_enums_v1_predicate_proto_enumTypes,
190 > }.Build()
191 > File_temporal_server_api_enums_v1_predicate_proto = out.File
192 > file_temporal_server_api_enums_v1_predicate_proto_goTypes = nil
193 > file_temporal_server_api_enums_v1_predicate_proto_depIdxs = nil
194 }
go.temporal.io/server/api/enums/v1/workflow_task_type.pb.go 23 covered LOC · 3 ranges

Open complete file

72 }
73
74 > func (WorkflowTaskType) Descriptor() protoreflect.EnumDescriptor { workflow_task_type.pb.go
75 > return file_temporal_server_api_enums_v1_workflow_task_type_proto_enumTypes[0].Descriptor()
76 > }
77
78 func (WorkflowTaskType) Type() protoreflect.EnumType {
124 }
125
126 > func init() { file_temporal_server_api_enums_v1_workflow_task_type_proto_init() } workflow_task_type.pb.go
127 > func file_temporal_server_api_enums_v1_workflow_task_type_proto_init() {
128 > if File_temporal_server_api_enums_v1_workflow_task_type_proto != nil {
129 return
130 }
131 > type x struct{} workflow_task_type.pb.go
132 > out := protoimpl.TypeBuilder{
133 > File: protoimpl.DescBuilder{
134 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
135 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_workflow_task_type_proto_rawDesc), len(file_temporal_server_api_enums_v1_workflow_task_type_proto_rawDesc)),
136 > NumEnums: 1,
137 > NumMessages: 0,
138 > NumExtensions: 0,
139 > NumServices: 0,
140 > },
141 > GoTypes: file_temporal_server_api_enums_v1_workflow_task_type_proto_goTypes,
142 > DependencyIndexes: file_temporal_server_api_enums_v1_workflow_task_type_proto_depIdxs,
143 > EnumInfos: file_temporal_server_api_enums_v1_workflow_task_type_proto_enumTypes,
144 > }.Build()
145 > File_temporal_server_api_enums_v1_workflow_task_type_proto = out.File
146 > file_temporal_server_api_enums_v1_workflow_task_type_proto_goTypes = nil
147 > file_temporal_server_api_enums_v1_workflow_task_type_proto_depIdxs = nil
148 }
go.temporal.io/server/chasm/lib/activity/config.go 23 covered LOC · 2 ranges

Open complete file

57 }
58
59 > func ConfigProvider(dc *dynamicconfig.Collection) *Config { config.go
60 > return &Config{
61 > BlobSizeLimitError: dynamicconfig.BlobSizeLimitError.Get(dc),
62 > BlobSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
63 > BreakdownMetricsByTaskQueue: dynamicconfig.MetricsBreakdownByTaskQueue.Get(dc),
64 > DefaultActivityRetryPolicy: dynamicconfig.DefaultActivityRetryPolicy.Get(dc),
65 > EnableCallbacks: EnableCallbacks.Get(dc),
66 > Enabled: Enabled.Get(dc),
67 > LongPollBuffer: LongPollBuffer.Get(dc),
68 > LongPollTimeout: LongPollTimeout.Get(dc),
69 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
70 > StartDelayEnabled: StartDelayEnabled.Get(dc),
71 > MaxCallbacksPerExecution: callback.MaxPerExecution.Get(dc),
72 > VisibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
73 > }
74 > }
75
76 // linkValidatorProvider builds the linkValidator from dynamic config.
77 > func linkValidatorProvider(dc *dynamicconfig.Collection) *linkValidator { config.go
78 > return newLinkValidator(
79 > dynamicconfig.FrontendMaxLinksPerRequest.Get(dc),
80 > dynamicconfig.MaxLinksPerComponent.Get(dc),
81 > dynamicconfig.FrontendLinkMaxSize.Get(dc),
82 > )
83 > }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/request_response.pb.go 23 covered LOC · 1 range

Open complete file

1021 }
1022
1023 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_init() } request_response.pb.go
1024 > func file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_init() {
1025 > if File_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto != nil {
1026 > return
1027 > }
1028 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_init()
1029 > type x struct{}
1030 > out := protoimpl.TypeBuilder{
1031 > File: protoimpl.DescBuilder{
1032 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1033 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_rawDesc)),
1034 > NumEnums: 0,
1035 > NumMessages: 18,
1036 > NumExtensions: 0,
1037 > NumServices: 0,
1038 > },
1039 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_goTypes,
1040 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_depIdxs,
1041 > MessageInfos: file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes,
1042 > }.Build()
1043 > File_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto = out.File
1044 > file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_goTypes = nil
1045 > file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_depIdxs = nil
1046 }
go.temporal.io/server/chasm/lib/workflow/nexus_library.go 23 covered LOC · 3 ranges

Open complete file

12 }
13
14 > func newNexusLibrary(config *nexusoperation.Config, nexusProcessor *chasm.NexusEndpointProcessor) *nexusLibrary { nexus_library.go
15 > return &nexusLibrary{config: config, nexusProcessor: nexusProcessor}
16 > }
17
18 > func (l *nexusLibrary) CommandHandlers() map[enumspb.CommandType]CommandHandler { nexus_library.go
19 > h := &nexusCommandHandler{config: l.config, nexusProcessor: l.nexusProcessor}
20 > return map[enumspb.CommandType]CommandHandler{
21 > enumspb.COMMAND_TYPE_SCHEDULE_NEXUS_OPERATION: h.handleScheduleCommand,
22 > enumspb.COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION: h.handleCancelCommand,
23 > }
24 > }
25
26 > func (l *nexusLibrary) EventDefinitions() []EventDefinition { nexus_library.go
27 > return []EventDefinition{
28 > ScheduledEventDefinition{},
29 > CancelRequestedEventDefinition{},
30 > CancelRequestCompletedEventDefinition{},
31 > CancelRequestFailedEventDefinition{},
32 > StartedEventDefinition{},
33 > CompletedEventDefinition{},
34 > FailedEventDefinition{},
35 > CanceledEventDefinition{},
36 > TimedOutEventDefinition{},
37 > }
38 > }
go.temporal.io/server/common/config/config.go 23 covered LOC · 8 ranges

Open complete file

693
694 // Validate validates this config
695 > func (c *Config) Validate() error { config.go
696 > if err := c.Persistence.Validate(); err != nil {
697 return err
698 }
699
700 > if err := c.Archival.Validate(&c.NamespaceDefaults.Archival); err != nil { config.go
701 return err
702 }
703
704 > _, hasIFE := c.Services[string(primitives.InternalFrontendService)] config.go
705 > if hasIFE && (c.PublicClient.HostPort != "" || c.PublicClient.ForceTLSConfig != "" || c.PublicClient.HTTPHostPort != "") {
706 return fmt.Errorf("when using internal-frontend, publicClient must be empty")
707 }
708
709 > switch c.PublicClient.ForceTLSConfig { config.go
710 > case ForceTLSConfigAuto, ForceTLSConfigInternode, ForceTLSConfigFrontend:
711 default:
712 return fmt.Errorf("invalid value for publicClient.forceTLSConfig: %q", c.PublicClient.ForceTLSConfig)
713 }
714
715 > return nil config.go
716 }
717
718 // String converts the config object into a string
719 > func (c *Config) String() string { config.go
720 > var buf bytes.Buffer
721 > encoder := yaml.NewEncoder(&buf)
722 > encoder.SetIndent(2)
723 > _ = encoder.Encode(c)
724 > maskedYaml, _ := masker.MaskYaml(buf.String(), masker.DefaultYAMLFieldNames)
725 > return maskedYaml
726 > }
727
728 > func (r *GroupTLS) IsServerEnabled() bool { config.go
729 > return r.Server.KeyFile != "" || r.Server.KeyData != ""
730 > }
731
732 > func (r *GroupTLS) IsClientEnabled() bool { config.go
733 > return len(r.Client.RootCAFiles) > 0 || len(r.Client.RootCAData) > 0 ||
734 > r.Client.ForceTLS
735 > }
736
737 func (p *JWTKeyProvider) HasSourceURIsConfigured() bool {
go.temporal.io/server/common/dynamicconfig/shared_structure.go 23 covered LOC · 6 ranges

Open complete file

17 )
18
19 > func warnDefaultSharedStructure(key string, def any) { shared_structure.go
20 > if path := hasSharedStructure(reflect.ValueOf(def), "root"); path != "" {
21 sharedStructureWarnings.Store(key, path)
22 }
23 }
24
25 > func logSharedStructureWarnings(logger log.Logger) { shared_structure.go
26 > // If you see this warning, it means that a default value used in New*TypedSetting has a
27 > // non-nil slice or map in it. That can lead to confusing behavior since the value from
28 > // dynamic config will be merged over the default value (e.g. the slice will be appended
29 > // to, not replaced). If that behavior is desired, you can avoid this warning by using
30 > // New*TypedSettingWithConverter and referring to dynamicconfig.ConvertStructure
31 > // explicitly. Otherwise use nil slices and maps, including at the top level
32 > // (so `[]string(nil)` instead of `[]string{}`).
33 > logSharedStructureWarningsOnce.Do(func() {
34 > sharedStructureWarnings.Range(func(key, path any) bool {
35 softassert.Fail(logger,
36 "default value contains shared structure",
42 }
43
44 > func hasSharedStructure(v reflect.Value, path string) string { shared_structure.go
45 > // nolint:exhaustive // deliberately not exhaustive
46 > switch v.Kind() {
47 > case reflect.Map, reflect.Slice, reflect.Pointer:
48 > if !v.IsNil() {
49 return path
50 }
51 > case reflect.Interface: shared_structure.go
52 > if !v.IsNil() {
53 return hasSharedStructure(v.Elem(), path)
54 }
55 > case reflect.Struct: shared_structure.go
56 > for i := range v.NumField() {
57 > if p := hasSharedStructure(v.Field(i), path+"."+v.Type().Field(i).Name); p != "" {
58 return p
59 }
go.temporal.io/server/common/log/throttle_logger.go 23 covered LOC · 5 ranges

Open complete file

21 //
22 // Fatal/Panic/DPanic logs are always emitted without any throttling
23 > func NewThrottledLogger(logger Logger, rps quotas.RateFn) *throttledLogger { throttle_logger.go
24 > if sl, ok := logger.(SkipLogger); ok {
25 logger = sl.Skip(extraSkipForThrottleLogger)
26 }
27
28 > limiter := quotas.NewDefaultOutgoingRateLimiter(rps) throttle_logger.go
29 > tl := &throttledLogger{
30 > limiter: limiter,
31 > logger: logger,
32 > }
33 > return tl
34 }
35
40 }
41
42 > func (tl *throttledLogger) Info(msg string, tags ...tag.Tag) { throttle_logger.go
43 > tl.rateLimit(func() {
44 > tl.logger.Info(msg, tags...)
45 > })
46 }
47
81
82 // Return a logger with the specified key-value pairs set, to be included in a subsequent normal logging call
83 > func (tl *throttledLogger) With(tags ...tag.Tag) Logger { throttle_logger.go
84 > result := &throttledLogger{
85 > limiter: tl.limiter,
86 > logger: With(tl.logger, tags...),
87 > }
88 > return result
89 > }
90
91 > func (tl *throttledLogger) rateLimit(f func()) { throttle_logger.go
92 > if tl.limiter.Allow() {
93 > f()
94 > }
95 }
96
go.temporal.io/server/common/persistence/visibility/store/sql/visibility_store.go 23 covered LOC · 5 ranges

Open complete file

69 metricsHandler metrics.Handler,
70 serializer serialization.Serializer,
71 > ) (*VisibilityStore, error) { visibility_store.go
72 > refDbConn := persistencesql.NewRefCountedDBConn(sqlplugin.DbKindVisibility, &cfg, r, logger, metricsHandler)
73 > db, err := refDbConn.Get()
74 > if err != nil {
75 return nil, err
76 }
77 > return &VisibilityStore{ visibility_store.go
78 > sqlStore: persistencesql.NewSQLStore(db, logger, serializer),
79 > searchAttributesProvider: searchAttributesProvider,
80 > searchAttributesMapperProvider: searchAttributesMapperProvider,
81 > chasmRegistry: chasmRegistry,
82 > metricsHandler: metricsHandler,
83 > logger: logger,
84 >
85 > enableUnifiedQueryConverter: enableUnifiedQueryConverter,
86 > }, nil
87 }
88
89 > func (s *VisibilityStore) Close() { visibility_store.go
90 > s.sqlStore.Close()
91 > }
92
93 > func (s *VisibilityStore) GetName() string { visibility_store.go
94 > return s.sqlStore.GetName()
95 > }
96
97 func convertSQLError(message string, err error) error {
102 }
103
104 > func (s *VisibilityStore) GetIndexName() string { visibility_store.go
105 > return s.sqlStore.GetDbName()
106 > }
107
108 func (s *VisibilityStore) ValidateCustomSearchAttributes(
go.temporal.io/server/common/pprof/pprof.go 23 covered LOC · 5 ranges

Open complete file

31
32 // NewInitializer create a new instance of PProf Initializer
33 > func NewInitializer(cfg *config.PProf, logger log.Logger) *PProfInitializerImpl { pprof.go
34 > return &PProfInitializerImpl{
35 > PProf: cfg,
36 > Logger: logger,
37 > }
38 > }
39
40 // Start the pprof based on config
41 > func (initializer *PProfInitializerImpl) Start() error { pprof.go
42 > port := initializer.PProf.Port
43 > if port == 0 {
44 initializer.Logger.Info("PProf not started due to port not set")
45 return nil
46 }
47 > host := initializer.PProf.Host pprof.go
48 > if host == "" {
49 > // default to localhost which will favor ipv4 on dual stack
50 > // environments - configure host as `::1` to bind on ipv6 localhost
51 > host = "localhost"
52 > }
53
54 > hostPort := net.JoinHostPort(host, fmt.Sprint(port)) pprof.go
55 >
56 > if atomic.CompareAndSwapInt32(&pprofStatus, pprofNotInitialized, pprofInitialized) {
57 > go func() {
58 > initializer.Logger.Info("PProf listen on ", tag.Host(host), tag.Port(port))
59 > err := http.ListenAndServe(hostPort, nil)
60 > if err != nil {
61 initializer.Logger.Error("listen and serve err", tag.Error(err))
62 }
63 }()
64 }
65 > return nil pprof.go
66 }
go.temporal.io/server/common/rpc/interceptor/routing_key_interceptor.go 23 covered LOC · 7 ranges

Open complete file

81 extractors []RoutingKeyExtractorFunc,
82 logger log.Logger,
83 > ) *RoutingKeyInterceptor { routing_key_interceptor.go
84 > return &RoutingKeyInterceptor{
85 > extractors: extractors,
86 > logger: logger,
87 > }
88 > }
89
90 // WithExtractors returns a new interceptor with additional extractors prepended.
106 info *grpc.UnaryServerInfo,
107 handler grpc.UnaryHandler,
108 > ) (any, error) { routing_key_interceptor.go
109 > // Try each extractor until one returns a non-empty businessID
110 > for _, extractor := range i.extractors {
111 > if key := extractor(ctx, req, info.FullMethod); key.ID != "" || key.Strategy != namespace.RoutingStrategyDefault {
112 > i.logger.Debug("routing key extraction: adding routing key to context", routing_key_interceptor.go
113 > tag.WorkflowID(key.ID),
114 > tag.String("grpc-method", info.FullMethod),
115 > )
116 > ctx = AddRoutingKeyToContext(ctx, key)
117 > break
118 }
119 }
120
121 > return handler(ctx, req) routing_key_interceptor.go
122 }
123
124 // AddRoutingKeyToContext adds the routing Key to the context
125 > func AddRoutingKeyToContext(ctx context.Context, routingKey namespace.RoutingKey) context.Context { routing_key_interceptor.go
126 > return context.WithValue(ctx, routingKeyCtxKey, routingKey)
127 > }
128
129 // GetRoutingKeyFromContext retrieves the routing Key from the context.
130 // Returns a zero-value RoutingKey if not found.
131 > func GetRoutingKeyFromContext(ctx context.Context) namespace.RoutingKey { routing_key_interceptor.go
132 > if key, ok := ctx.Value(routingKeyCtxKey).(namespace.RoutingKey); ok {
133 return key
134 }
135 > return namespace.RoutingKey{} routing_key_interceptor.go
136 }
go.temporal.io/server/service/history/handler.go 23 covered LOC · 4 ranges

Open complete file

173
174 // Start starts the handler
175 > func (h *Handler) Start() { handler.go
176 > if !atomic.CompareAndSwapInt32(
177 > &h.status,
178 > common.DaemonStatusInitialized,
179 > common.DaemonStatusStarted,
180 > ) {
181 return
182 }
183
184 > h.replicationTaskFetcherFactory.Start() handler.go
185 > h.streamReceiverMonitor.Start()
186 > // events notifier must starts before controller
187 > h.eventNotifier.Start()
188 > h.controller.Start()
189 > h.dlqMetricsEmitter.Start()
190 }
191
192 // Stop stops the handler
193 > func (h *Handler) Stop() { handler.go
194 > if !atomic.CompareAndSwapInt32(
195 > &h.status,
196 > common.DaemonStatusStarted,
197 > common.DaemonStatusStopped,
198 > ) {
199 return
200 }
201
202 > h.streamReceiverMonitor.Stop() handler.go
203 > h.replicationTaskFetcherFactory.Stop()
204 > h.controller.Stop()
205 > h.eventNotifier.Stop()
206 > h.dlqMetricsEmitter.Stop()
207 }
208
go.temporal.io/server/service/history/transfer_queue_task_executor_base.go 23 covered LOC · 1 range

Open complete file

69 visibilityManager manager.VisibilityManager,
70 chasmEngine chasm.Engine,
71 > ) *transferQueueTaskExecutorBase { transfer_queue_task_executor_base.go
72 > return &transferQueueTaskExecutorBase{
73 > currentClusterName: shardContext.GetClusterMetadata().GetCurrentClusterName(),
74 > shardContext: shardContext,
75 > registry: shardContext.GetNamespaceRegistry(),
76 > cache: workflowCache,
77 > logger: logger,
78 > metricHandler: metricHandler,
79 > historyRawClient: historyRawClient,
80 > matchingRawClient: matchingRawClient,
81 > config: shardContext.GetConfig(),
82 > searchAttributesProvider: shardContext.GetSearchAttributesProvider(),
83 > visibilityManager: visibilityManager,
84 > workflowDeleteManager: deletemanager.NewDeleteManager(
85 > shardContext,
86 > workflowCache,
87 > shardContext.GetConfig(),
88 > shardContext.GetTimeSource(),
89 > visibilityManager,
90 > ),
91 > chasmEngine: chasmEngine,
92 > }
93 > }
94
95 func (t *transferQueueTaskExecutorBase) pushActivity(
go.temporal.io/server/api/common/v1/api_category.pb.go 22 covered LOC · 2 ranges

Open complete file

204 }
205
206 > func init() { file_temporal_server_api_common_v1_api_category_proto_init() } api_category.pb.go
207 > func file_temporal_server_api_common_v1_api_category_proto_init() {
208 > if File_temporal_server_api_common_v1_api_category_proto != nil {
209 return
210 }
211 > type x struct{} api_category.pb.go
212 > out := protoimpl.TypeBuilder{
213 > File: protoimpl.DescBuilder{
214 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
215 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_common_v1_api_category_proto_rawDesc), len(file_temporal_server_api_common_v1_api_category_proto_rawDesc)),
216 > NumEnums: 1,
217 > NumMessages: 1,
218 > NumExtensions: 1,
219 > NumServices: 0,
220 > },
221 > GoTypes: file_temporal_server_api_common_v1_api_category_proto_goTypes,
222 > DependencyIndexes: file_temporal_server_api_common_v1_api_category_proto_depIdxs,
223 > EnumInfos: file_temporal_server_api_common_v1_api_category_proto_enumTypes,
224 > MessageInfos: file_temporal_server_api_common_v1_api_category_proto_msgTypes,
225 > ExtensionInfos: file_temporal_server_api_common_v1_api_category_proto_extTypes,
226 > }.Build()
227 > File_temporal_server_api_common_v1_api_category_proto = out.File
228 > file_temporal_server_api_common_v1_api_category_proto_goTypes = nil
229 > file_temporal_server_api_common_v1_api_category_proto_depIdxs = nil
230 }
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/request_response.pb.go 22 covered LOC · 1 range

Open complete file

1057 }
1058
1059 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_init() } request_response.pb.go
1060 > func file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_init() {
1061 > if File_temporal_server_chasm_lib_activity_proto_v1_request_response_proto != nil {
1062 > return
1063 > }
1064 > type x struct{}
1065 > out := protoimpl.TypeBuilder{
1066 > File: protoimpl.DescBuilder{
1067 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1068 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_rawDesc)),
1069 > NumEnums: 0,
1070 > NumMessages: 20,
1071 > NumExtensions: 0,
1072 > NumServices: 0,
1073 > },
1074 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_goTypes,
1075 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_depIdxs,
1076 > MessageInfos: file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes,
1077 > }.Build()
1078 > File_temporal_server_chasm_lib_activity_proto_v1_request_response_proto = out.File
1079 > file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_goTypes = nil
1080 > file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_depIdxs = nil
1081 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/request_response.pb.go 22 covered LOC · 1 range

Open complete file

672 }
673
674 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_init() } request_response.pb.go
675 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_init() {
676 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto != nil {
677 > return
678 > }
679 > type x struct{}
680 > out := protoimpl.TypeBuilder{
681 > File: protoimpl.DescBuilder{
682 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
683 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_rawDesc)),
684 > NumEnums: 0,
685 > NumMessages: 12,
686 > NumExtensions: 0,
687 > NumServices: 0,
688 > },
689 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_goTypes,
690 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_depIdxs,
691 > MessageInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes,
692 > }.Build()
693 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto = out.File
694 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_goTypes = nil
695 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_depIdxs = nil
696 }
go.temporal.io/server/chasm/lib/tests/gen/testspb/v1/request_response.pb.go 22 covered LOC · 1 range

Open complete file

157 }
158
159 > func init() { file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_init() } request_response.pb.go
160 > func file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_init() {
161 > if File_temporal_server_chasm_lib_tests_proto_v1_request_response_proto != nil {
162 > return
163 > }
164 > type x struct{}
165 > out := protoimpl.TypeBuilder{
166 > File: protoimpl.DescBuilder{
167 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
168 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_rawDesc)),
169 > NumEnums: 0,
170 > NumMessages: 2,
171 > NumExtensions: 0,
172 > NumServices: 0,
173 > },
174 > GoTypes: file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_goTypes,
175 > DependencyIndexes: file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_depIdxs,
176 > MessageInfos: file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_msgTypes,
177 > }.Build()
178 > File_temporal_server_chasm_lib_tests_proto_v1_request_response_proto = out.File
179 > file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_goTypes = nil
180 > file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_depIdxs = nil
181 }
go.temporal.io/server/api/persistence/v1/task_queues.pb.go 21 covered LOC · 2 ranges

Open complete file

899 }
900
901 > func init() { file_temporal_server_api_persistence_v1_task_queues_proto_init() } task_queues.pb.go
902 > func file_temporal_server_api_persistence_v1_task_queues_proto_init() {
903 > if File_temporal_server_api_persistence_v1_task_queues_proto != nil {
904 return
905 }
906 > type x struct{} task_queues.pb.go
907 > out := protoimpl.TypeBuilder{
908 > File: protoimpl.DescBuilder{
909 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
910 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_task_queues_proto_rawDesc), len(file_temporal_server_api_persistence_v1_task_queues_proto_rawDesc)),
911 > NumEnums: 1,
912 > NumMessages: 13,
913 > NumExtensions: 0,
914 > NumServices: 0,
915 > },
916 > GoTypes: file_temporal_server_api_persistence_v1_task_queues_proto_goTypes,
917 > DependencyIndexes: file_temporal_server_api_persistence_v1_task_queues_proto_depIdxs,
918 > EnumInfos: file_temporal_server_api_persistence_v1_task_queues_proto_enumTypes,
919 > MessageInfos: file_temporal_server_api_persistence_v1_task_queues_proto_msgTypes,
920 > }.Build()
921 > File_temporal_server_api_persistence_v1_task_queues_proto = out.File
922 > file_temporal_server_api_persistence_v1_task_queues_proto_goTypes = nil
923 > file_temporal_server_api_persistence_v1_task_queues_proto_depIdxs = nil
924 }
go.temporal.io/server/api/routing/v1/extension.pb.go 21 covered LOC · 2 ranges

Open complete file

144 }
145
146 > func init() { file_temporal_server_api_routing_v1_extension_proto_init() } extension.pb.go
147 > func file_temporal_server_api_routing_v1_extension_proto_init() {
148 > if File_temporal_server_api_routing_v1_extension_proto != nil {
149 return
150 }
151 > type x struct{} extension.pb.go
152 > out := protoimpl.TypeBuilder{
153 > File: protoimpl.DescBuilder{
154 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
155 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_routing_v1_extension_proto_rawDesc), len(file_temporal_server_api_routing_v1_extension_proto_rawDesc)),
156 > NumEnums: 0,
157 > NumMessages: 1,
158 > NumExtensions: 1,
159 > NumServices: 0,
160 > },
161 > GoTypes: file_temporal_server_api_routing_v1_extension_proto_goTypes,
162 > DependencyIndexes: file_temporal_server_api_routing_v1_extension_proto_depIdxs,
163 > MessageInfos: file_temporal_server_api_routing_v1_extension_proto_msgTypes,
164 > ExtensionInfos: file_temporal_server_api_routing_v1_extension_proto_extTypes,
165 > }.Build()
166 > File_temporal_server_api_routing_v1_extension_proto = out.File
167 > file_temporal_server_api_routing_v1_extension_proto_goTypes = nil
168 > file_temporal_server_api_routing_v1_extension_proto_depIdxs = nil
169 }
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/tasks.pb.go 21 covered LOC · 2 ranges

Open complete file

495 }
496
497 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_init() } tasks.pb.go
498 > func file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_init() {
499 > if File_temporal_server_chasm_lib_activity_proto_v1_tasks_proto != nil {
500 return
501 }
502 > type x struct{} tasks.pb.go
503 > out := protoimpl.TypeBuilder{
504 > File: protoimpl.DescBuilder{
505 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
506 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_rawDesc)),
507 > NumEnums: 2,
508 > NumMessages: 5,
509 > NumExtensions: 0,
510 > NumServices: 0,
511 > },
512 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_goTypes,
513 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_depIdxs,
514 > EnumInfos: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_enumTypes,
515 > MessageInfos: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_msgTypes,
516 > }.Build()
517 > File_temporal_server_chasm_lib_activity_proto_v1_tasks_proto = out.File
518 > file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_goTypes = nil
519 > file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_depIdxs = nil
520 }
go.temporal.io/server/common/masker/masker.go 21 covered LOC · 6 ranges

Open complete file

16 // MaskYaml replace password values with mask and returns copy of the string.
17 // Does recursive replacement for entire yamlStr.
18 > func MaskYaml(yamlStr string, fieldNamesToMask []string) (string, error) { masker.go
19 > fns := make(map[string]struct{}, len(fieldNamesToMask))
20 > for _, fieldName := range fieldNamesToMask {
21 > fns[fieldName] = struct{}{}
22 > }
23
24 > var parsedYaml map[string]any masker.go
25 > err := yaml.Unmarshal([]byte(yamlStr), &parsedYaml)
26 > if err != nil {
27 return yamlStr, err
28 }
29
30 > maskMap(parsedYaml, fns) masker.go
31 >
32 > strBytes, err := yaml.Marshal(parsedYaml)
33 > if err != nil {
34 return yamlStr, err
35 }
36 > return string(strBytes), nil masker.go
37 }
38
71 }
72
73 > func maskMap(m map[string]any, fns map[string]struct{}) { masker.go
74 > for key, value := range m {
75 > if _, ok := fns[key]; ok {
76 > m[key] = passwordMask
77 > }
78
79 > if valueMap, ok := value.(map[string]any); ok { masker.go
80 > maskMap(valueMap, fns)
81 > }
82 }
83 }
go.temporal.io/server/common/persistence/sql/store.go 21 covered LOC · 9 ranges

Open complete file

19
20 // RegisterPlugin will register a SQL plugin
21 > func RegisterPlugin(pluginName string, plugin sqlplugin.Plugin) { store.go
22 > if _, ok := supportedPlugins[pluginName]; ok {
23 panic("plugin " + pluginName + " already registered")
24 }
25 > supportedPlugins[pluginName] = plugin store.go
26 }
27
36 logger log.Logger,
37 mh metrics.Handler,
38 > ) (sqlplugin.DB, error) { store.go
39 > return createDB[sqlplugin.DB](dbKind, cfg, r, logger, mh)
40 > }
41
42 // NewSQLAdminDB returns a AdminDB.
47 logger log.Logger,
48 mh metrics.Handler,
49 > ) (sqlplugin.AdminDB, error) { store.go
50 > return createDB[sqlplugin.AdminDB](dbKind, cfg, r, logger, mh)
51 > }
52
53 func createDB[T any](
57 logger log.Logger,
58 mh metrics.Handler,
59 > ) (T, error) { store.go
60 > var res T
61 > plugin, err := getPlugin(cfg.PluginName)
62 > if err != nil {
63 return res, err
64 }
65 > db, err := plugin.CreateDB(dbKind, cfg, r, logger, mh) store.go
66 > if err != nil {
67 return res, err
68 }
69 //revive:disable-next-line:unchecked-type-assertion
70 > res = db.(T) store.go
71 > return res, err
72 }
73
74 > func getPlugin(pluginName string) (sqlplugin.Plugin, error) { store.go
75 > plugin, ok := supportedPlugins[pluginName]
76 > if !ok {
77 keys := expmaps.Keys(supportedPlugins)
78 slices.Sort(keys)
84 )
85 }
86 > return plugin, nil store.go
87 }
88
go.temporal.io/server/common/persistence/sql/version_checker.go 21 covered LOC · 7 ranges

Open complete file

15 r resolver.ServiceResolver,
16 logger log.Logger,
17 > ) error { version_checker.go
18 >
19 > if err := checkMainDatabase(cfg, r, logger); err != nil {
20 return err
21 }
22 > if cfg.VisibilityConfigExist() { version_checker.go
23 > return checkVisibilityDatabase(cfg, r, logger)
24 > }
25 return nil
26 }
30 r resolver.ServiceResolver,
31 logger log.Logger,
32 > ) error { version_checker.go
33 > ds, ok := cfg.DataStores[cfg.DefaultStore]
34 > if ok && ds.SQL != nil {
35 > return checkCompatibleVersion(ds.SQL, r, sqlplugin.DbKindMain, logger)
36 > }
37 return nil
38 }
42 r resolver.ServiceResolver,
43 logger log.Logger,
44 > ) error { version_checker.go
45 > ds, ok := cfg.DataStores[cfg.VisibilityStore]
46 > if ok && ds.SQL != nil {
47 > return checkCompatibleVersion(ds.SQL, r, sqlplugin.DbKindVisibility, logger)
48 > }
49 return nil
50 }
55 dbKind sqlplugin.DbKind,
56 logger log.Logger,
57 > ) error { version_checker.go
58 > db, err := NewSQLAdminDB(dbKind, cfg, r, logger, metrics.NoopMetricsHandler)
59 > if err != nil {
60 return err
61 }
62 > defer func() { _ = db.Close() }() version_checker.go
63
64 > return db.VerifyVersion() version_checker.go
65 }
go.temporal.io/server/common/tasks/group_by_scheduler.go 21 covered LOC · 7 ranges

Open complete file

34
35 // NewGroupByScheduler creates a new [GroupByScheduler] from given options.
36 > func NewGroupByScheduler[K comparable, T Task](options GroupBySchedulerOptions[K, T]) *GroupByScheduler[K, T] { group_by_scheduler.go
37 > return &GroupByScheduler[K, T]{
38 > options: options,
39 > schedulers: make(map[K]RunnableScheduler),
40 > }
41 > }
42
43 > func (*GroupByScheduler[K, T]) Start() { group_by_scheduler.go
44 > // noop
45 > }
46
47 // Stop signals running tasks to stop, aborts any pending tasks and waits up to a minute for all running tasks to
48 // complete.
49 > func (s *GroupByScheduler[K, T]) Stop() { group_by_scheduler.go
50 > if !s.stopped.CompareAndSwap(false, true) {
51 return
52 }
53 > s.mu.Lock() group_by_scheduler.go
54 > for _, lim := range s.schedulers {
55 lim.InitiateShutdown()
56 }
57 > s.mu.Unlock() group_by_scheduler.go
58 >
59 > if success := common.BlockWithTimeout(s.waitShutdown, time.Minute); !success {
60 s.options.Logger.Warn("GroupByScheduler timed out waiting for groups to complete shutdown")
61 > } else { group_by_scheduler.go
62 > s.options.Logger.Debug("GroupByScheduler shutdown complete")
63 > }
64 }
65
66 > func (s *GroupByScheduler[K, T]) waitShutdown() { group_by_scheduler.go
67 > for _, lim := range s.schedulers {
68 lim.WaitShutdown()
69 }
go.temporal.io/server/service/frontend/openapi_http_handler.go 21 covered LOC · 3 ranges

Open complete file

24 rateLimitInterceptor *interceptor.RateLimitInterceptor,
25 logger log.Logger,
26 > ) *OpenAPIHTTPHandler { openapi_http_handler.go
27 > return &OpenAPIHTTPHandler{
28 > logger: logger,
29 > rateLimitInterceptor: rateLimitInterceptor,
30 > }
31 > }
32
33 > func (h *OpenAPIHTTPHandler) RegisterRoutes(r *mux.Router) { openapi_http_handler.go
34 > serve := func(version int, apiName string, contentType string, spec []byte) func(http.ResponseWriter, *http.Request) {
35 > return func(w http.ResponseWriter, r *http.Request) {
36 if err := h.rateLimitInterceptor.Allow(apiName, r.Header); err != nil {
37 w.WriteHeader(http.StatusTooManyRequests)
54 }
55
56 > r.PathPrefix("/swagger.json").Methods("GET").HandlerFunc(serve( openapi_http_handler.go
57 > 2,
58 > configs.OpenAPIV2APIName,
59 > "application/vnd.oai.openapi+json;version=2.0",
60 > openapi.OpenAPIV2JSONSpec,
61 > ))
62 > r.PathPrefix("/openapi.yaml").Methods("GET").HandlerFunc(serve(
63 > 3,
64 > configs.OpenAPIV3APIName,
65 > "application/vnd.oai.openapi;version=3.0",
66 > openapi.OpenAPIV3YAMLSpec,
67 > ))
68 }
go.temporal.io/server/service/history/queues/executable_factory.go 21 covered LOC · 1 range

Open complete file

64 dlqInternalErrors dynamicconfig.BoolPropertyFn,
65 dlqErrorPattern dynamicconfig.StringPropertyFn,
66 > ) *executableFactoryImpl { executable_factory.go
67 > return &executableFactoryImpl{
68 > executor: executor,
69 > scheduler: scheduler,
70 > rescheduler: rescheduler,
71 > priorityAssigner: priorityAssigner,
72 > timeSource: timeSource,
73 > namespaceRegistry: namespaceRegistry,
74 > clusterMetadata: clusterMetadata,
75 > chasmRegistry: chasmRegistry,
76 > taskTypeTagProvider: taskTypeTagProvider,
77 > logger: logger,
78 > metricsHandler: metricsHandler,
79 > tracer: tracer,
80 > dlqWriter: dlqWriter,
81 > dlqEnabled: dlqEnabled,
82 > attemptsBeforeSendingToDlq: attemptsBeforeSendingToDlq,
83 > dlqInternalErrors: dlqInternalErrors,
84 > dlqErrorPattern: dlqErrorPattern,
85 > }
86 > }
87
88 func (f *executableFactoryImpl) NewExecutable(task tasks.Task, readerID int64) Executable {
go.temporal.io/server/temporal/server_options.go 21 covered LOC · 9 ranges

Open complete file

66 )
67
68 > func newServerOptions(opts []ServerOption) *serverOptions { server_options.go
69 > so := &serverOptions{
70 > // Set defaults here.
71 > persistenceServiceResolver: resolver.NewNoopResolver(),
72 > }
73 > for _, opt := range opts {
74 > opt.apply(so)
75 > }
76
77 > return so server_options.go
78 }
79
80 > func (so *serverOptions) loadAndValidate() error { server_options.go
81 > for serviceName := range so.serviceNames {
82 > if !slices.Contains(Services, string(serviceName)) {
83 return fmt.Errorf("invalid service %q in service list %v", serviceName, so.serviceNames)
84 }
85 }
86
87 > if so.config == nil { server_options.go
88 err := so.loadConfig()
89 if err != nil {
92 }
93
94 > err := so.validateConfig() server_options.go
95 > if err != nil {
96 return fmt.Errorf("config validation error: %w", err)
97 }
98
99 > return nil server_options.go
100 }
101
126 }
127
128 > func (so *serverOptions) validateConfig() error { server_options.go
129 > if err := so.config.Validate(); err != nil {
130 return err
131 }
132
133 > for name := range so.serviceNames { server_options.go
134 > if _, ok := so.config.Services[string(name)]; !ok {
135 return fmt.Errorf("%q service is missing in config", name)
136 }
137 }
138 > return nil server_options.go
139 }
go.temporal.io/server/api/adminservice/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

273 }
274
275 > func init() { file_temporal_server_api_adminservice_v1_service_proto_init() } service.pb.go
276 > func file_temporal_server_api_adminservice_v1_service_proto_init() {
277 > if File_temporal_server_api_adminservice_v1_service_proto != nil {
278 return
279 }
280 > file_temporal_server_api_adminservice_v1_request_response_proto_init() service.pb.go
281 > type x struct{}
282 > out := protoimpl.TypeBuilder{
283 > File: protoimpl.DescBuilder{
284 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
285 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_adminservice_v1_service_proto_rawDesc), len(file_temporal_server_api_adminservice_v1_service_proto_rawDesc)),
286 > NumEnums: 0,
287 > NumMessages: 0,
288 > NumExtensions: 0,
289 > NumServices: 1,
290 > },
291 > GoTypes: file_temporal_server_api_adminservice_v1_service_proto_goTypes,
292 > DependencyIndexes: file_temporal_server_api_adminservice_v1_service_proto_depIdxs,
293 > }.Build()
294 > File_temporal_server_api_adminservice_v1_service_proto = out.File
295 > file_temporal_server_api_adminservice_v1_service_proto_goTypes = nil
296 > file_temporal_server_api_adminservice_v1_service_proto_depIdxs = nil
297 }
go.temporal.io/server/api/archiver/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

431 }
432
433 > func init() { file_temporal_server_api_archiver_v1_message_proto_init() } message.pb.go
434 > func file_temporal_server_api_archiver_v1_message_proto_init() {
435 > if File_temporal_server_api_archiver_v1_message_proto != nil {
436 return
437 }
438 > type x struct{} message.pb.go
439 > out := protoimpl.TypeBuilder{
440 > File: protoimpl.DescBuilder{
441 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
442 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_archiver_v1_message_proto_rawDesc), len(file_temporal_server_api_archiver_v1_message_proto_rawDesc)),
443 > NumEnums: 0,
444 > NumMessages: 4,
445 > NumExtensions: 0,
446 > NumServices: 0,
447 > },
448 > GoTypes: file_temporal_server_api_archiver_v1_message_proto_goTypes,
449 > DependencyIndexes: file_temporal_server_api_archiver_v1_message_proto_depIdxs,
450 > MessageInfos: file_temporal_server_api_archiver_v1_message_proto_msgTypes,
451 > }.Build()
452 > File_temporal_server_api_archiver_v1_message_proto = out.File
453 > file_temporal_server_api_archiver_v1_message_proto_goTypes = nil
454 > file_temporal_server_api_archiver_v1_message_proto_depIdxs = nil
455 }
go.temporal.io/server/api/batch/v1/request_response.pb.go 20 covered LOC · 2 ranges

Open complete file

180 }
181
182 > func init() { file_temporal_server_api_batch_v1_request_response_proto_init() } request_response.pb.go
183 > func file_temporal_server_api_batch_v1_request_response_proto_init() {
184 > if File_temporal_server_api_batch_v1_request_response_proto != nil {
185 return
186 }
187 > type x struct{} request_response.pb.go
188 > out := protoimpl.TypeBuilder{
189 > File: protoimpl.DescBuilder{
190 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
191 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_batch_v1_request_response_proto_rawDesc), len(file_temporal_server_api_batch_v1_request_response_proto_rawDesc)),
192 > NumEnums: 0,
193 > NumMessages: 1,
194 > NumExtensions: 0,
195 > NumServices: 0,
196 > },
197 > GoTypes: file_temporal_server_api_batch_v1_request_response_proto_goTypes,
198 > DependencyIndexes: file_temporal_server_api_batch_v1_request_response_proto_depIdxs,
199 > MessageInfos: file_temporal_server_api_batch_v1_request_response_proto_msgTypes,
200 > }.Build()
201 > File_temporal_server_api_batch_v1_request_response_proto = out.File
202 > file_temporal_server_api_batch_v1_request_response_proto_goTypes = nil
203 > file_temporal_server_api_batch_v1_request_response_proto_depIdxs = nil
204 }
go.temporal.io/server/api/chasm/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

206 }
207
208 > func init() { file_temporal_server_api_chasm_v1_message_proto_init() } message.pb.go
209 > func file_temporal_server_api_chasm_v1_message_proto_init() {
210 > if File_temporal_server_api_chasm_v1_message_proto != nil {
211 return
212 }
213 > type x struct{} message.pb.go
214 > out := protoimpl.TypeBuilder{
215 > File: protoimpl.DescBuilder{
216 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
217 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_chasm_v1_message_proto_rawDesc), len(file_temporal_server_api_chasm_v1_message_proto_rawDesc)),
218 > NumEnums: 0,
219 > NumMessages: 1,
220 > NumExtensions: 0,
221 > NumServices: 0,
222 > },
223 > GoTypes: file_temporal_server_api_chasm_v1_message_proto_goTypes,
224 > DependencyIndexes: file_temporal_server_api_chasm_v1_message_proto_depIdxs,
225 > MessageInfos: file_temporal_server_api_chasm_v1_message_proto_msgTypes,
226 > }.Build()
227 > File_temporal_server_api_chasm_v1_message_proto = out.File
228 > file_temporal_server_api_chasm_v1_message_proto_goTypes = nil
229 > file_temporal_server_api_chasm_v1_message_proto_depIdxs = nil
230 }
go.temporal.io/server/api/checksum/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

334 }
335
336 > func init() { file_temporal_server_api_checksum_v1_message_proto_init() } message.pb.go
337 > func file_temporal_server_api_checksum_v1_message_proto_init() {
338 > if File_temporal_server_api_checksum_v1_message_proto != nil {
339 return
340 }
341 > type x struct{} message.pb.go
342 > out := protoimpl.TypeBuilder{
343 > File: protoimpl.DescBuilder{
344 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
345 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_checksum_v1_message_proto_rawDesc), len(file_temporal_server_api_checksum_v1_message_proto_rawDesc)),
346 > NumEnums: 0,
347 > NumMessages: 1,
348 > NumExtensions: 0,
349 > NumServices: 0,
350 > },
351 > GoTypes: file_temporal_server_api_checksum_v1_message_proto_goTypes,
352 > DependencyIndexes: file_temporal_server_api_checksum_v1_message_proto_depIdxs,
353 > MessageInfos: file_temporal_server_api_checksum_v1_message_proto_msgTypes,
354 > }.Build()
355 > File_temporal_server_api_checksum_v1_message_proto = out.File
356 > file_temporal_server_api_checksum_v1_message_proto_goTypes = nil
357 > file_temporal_server_api_checksum_v1_message_proto_depIdxs = nil
358 }
go.temporal.io/server/api/cluster/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

342 }
343
344 > func init() { file_temporal_server_api_cluster_v1_message_proto_init() } message.pb.go
345 > func file_temporal_server_api_cluster_v1_message_proto_init() {
346 > if File_temporal_server_api_cluster_v1_message_proto != nil {
347 return
348 }
349 > type x struct{} message.pb.go
350 > out := protoimpl.TypeBuilder{
351 > File: protoimpl.DescBuilder{
352 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
353 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_cluster_v1_message_proto_rawDesc), len(file_temporal_server_api_cluster_v1_message_proto_rawDesc)),
354 > NumEnums: 0,
355 > NumMessages: 4,
356 > NumExtensions: 0,
357 > NumServices: 0,
358 > },
359 > GoTypes: file_temporal_server_api_cluster_v1_message_proto_goTypes,
360 > DependencyIndexes: file_temporal_server_api_cluster_v1_message_proto_depIdxs,
361 > MessageInfos: file_temporal_server_api_cluster_v1_message_proto_msgTypes,
362 > }.Build()
363 > File_temporal_server_api_cluster_v1_message_proto = out.File
364 > file_temporal_server_api_cluster_v1_message_proto_goTypes = nil
365 > file_temporal_server_api_cluster_v1_message_proto_depIdxs = nil
366 }
go.temporal.io/server/api/common/v1/dlq.pb.go 20 covered LOC · 2 ranges

Open complete file

295 }
296
297 > func init() { file_temporal_server_api_common_v1_dlq_proto_init() } dlq.pb.go
298 > func file_temporal_server_api_common_v1_dlq_proto_init() {
299 > if File_temporal_server_api_common_v1_dlq_proto != nil {
300 return
301 }
302 > type x struct{} dlq.pb.go
303 > out := protoimpl.TypeBuilder{
304 > File: protoimpl.DescBuilder{
305 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
306 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_common_v1_dlq_proto_rawDesc), len(file_temporal_server_api_common_v1_dlq_proto_rawDesc)),
307 > NumEnums: 0,
308 > NumMessages: 4,
309 > NumExtensions: 0,
310 > NumServices: 0,
311 > },
312 > GoTypes: file_temporal_server_api_common_v1_dlq_proto_goTypes,
313 > DependencyIndexes: file_temporal_server_api_common_v1_dlq_proto_depIdxs,
314 > MessageInfos: file_temporal_server_api_common_v1_dlq_proto_msgTypes,
315 > }.Build()
316 > File_temporal_server_api_common_v1_dlq_proto = out.File
317 > file_temporal_server_api_common_v1_dlq_proto_goTypes = nil
318 > file_temporal_server_api_common_v1_dlq_proto_depIdxs = nil
319 }
go.temporal.io/server/api/contextpropagation/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

109 }
110
111 > func init() { file_temporal_server_api_contextpropagation_v1_message_proto_init() } message.pb.go
112 > func file_temporal_server_api_contextpropagation_v1_message_proto_init() {
113 > if File_temporal_server_api_contextpropagation_v1_message_proto != nil {
114 return
115 }
116 > type x struct{} message.pb.go
117 > out := protoimpl.TypeBuilder{
118 > File: protoimpl.DescBuilder{
119 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
120 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_contextpropagation_v1_message_proto_rawDesc), len(file_temporal_server_api_contextpropagation_v1_message_proto_rawDesc)),
121 > NumEnums: 0,
122 > NumMessages: 2,
123 > NumExtensions: 0,
124 > NumServices: 0,
125 > },
126 > GoTypes: file_temporal_server_api_contextpropagation_v1_message_proto_goTypes,
127 > DependencyIndexes: file_temporal_server_api_contextpropagation_v1_message_proto_depIdxs,
128 > MessageInfos: file_temporal_server_api_contextpropagation_v1_message_proto_msgTypes,
129 > }.Build()
130 > File_temporal_server_api_contextpropagation_v1_message_proto = out.File
131 > file_temporal_server_api_contextpropagation_v1_message_proto_goTypes = nil
132 > file_temporal_server_api_contextpropagation_v1_message_proto_depIdxs = nil
133 }
go.temporal.io/server/api/deployment/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

4626 }
4627
4628 > func init() { file_temporal_server_api_deployment_v1_message_proto_init() } message.pb.go
4629 > func file_temporal_server_api_deployment_v1_message_proto_init() {
4630 > if File_temporal_server_api_deployment_v1_message_proto != nil {
4631 return
4632 }
4633 > type x struct{} message.pb.go
4634 > out := protoimpl.TypeBuilder{
4635 > File: protoimpl.DescBuilder{
4636 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
4637 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_deployment_v1_message_proto_rawDesc), len(file_temporal_server_api_deployment_v1_message_proto_rawDesc)),
4638 > NumEnums: 0,
4639 > NumMessages: 75,
4640 > NumExtensions: 0,
4641 > NumServices: 0,
4642 > },
4643 > GoTypes: file_temporal_server_api_deployment_v1_message_proto_goTypes,
4644 > DependencyIndexes: file_temporal_server_api_deployment_v1_message_proto_depIdxs,
4645 > MessageInfos: file_temporal_server_api_deployment_v1_message_proto_msgTypes,
4646 > }.Build()
4647 > File_temporal_server_api_deployment_v1_message_proto = out.File
4648 > file_temporal_server_api_deployment_v1_message_proto_goTypes = nil
4649 > file_temporal_server_api_deployment_v1_message_proto_depIdxs = nil
4650 }
go.temporal.io/server/api/enums/v1/cluster.pb.go 20 covered LOC · 2 ranges

Open complete file

209 }
210
211 > func init() { file_temporal_server_api_enums_v1_cluster_proto_init() } cluster.pb.go
212 > func file_temporal_server_api_enums_v1_cluster_proto_init() {
213 > if File_temporal_server_api_enums_v1_cluster_proto != nil {
214 return
215 }
216 > type x struct{} cluster.pb.go
217 > out := protoimpl.TypeBuilder{
218 > File: protoimpl.DescBuilder{
219 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
220 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_cluster_proto_rawDesc), len(file_temporal_server_api_enums_v1_cluster_proto_rawDesc)),
221 > NumEnums: 2,
222 > NumMessages: 0,
223 > NumExtensions: 0,
224 > NumServices: 0,
225 > },
226 > GoTypes: file_temporal_server_api_enums_v1_cluster_proto_goTypes,
227 > DependencyIndexes: file_temporal_server_api_enums_v1_cluster_proto_depIdxs,
228 > EnumInfos: file_temporal_server_api_enums_v1_cluster_proto_enumTypes,
229 > }.Build()
230 > File_temporal_server_api_enums_v1_cluster_proto = out.File
231 > file_temporal_server_api_enums_v1_cluster_proto_goTypes = nil
232 > file_temporal_server_api_enums_v1_cluster_proto_depIdxs = nil
233 }
go.temporal.io/server/api/enums/v1/dlq.pb.go 20 covered LOC · 2 ranges

Open complete file

187 }
188
189 > func init() { file_temporal_server_api_enums_v1_dlq_proto_init() } dlq.pb.go
190 > func file_temporal_server_api_enums_v1_dlq_proto_init() {
191 > if File_temporal_server_api_enums_v1_dlq_proto != nil {
192 return
193 }
194 > type x struct{} dlq.pb.go
195 > out := protoimpl.TypeBuilder{
196 > File: protoimpl.DescBuilder{
197 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
198 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_dlq_proto_rawDesc), len(file_temporal_server_api_enums_v1_dlq_proto_rawDesc)),
199 > NumEnums: 2,
200 > NumMessages: 0,
201 > NumExtensions: 0,
202 > NumServices: 0,
203 > },
204 > GoTypes: file_temporal_server_api_enums_v1_dlq_proto_goTypes,
205 > DependencyIndexes: file_temporal_server_api_enums_v1_dlq_proto_depIdxs,
206 > EnumInfos: file_temporal_server_api_enums_v1_dlq_proto_enumTypes,
207 > }.Build()
208 > File_temporal_server_api_enums_v1_dlq_proto = out.File
209 > file_temporal_server_api_enums_v1_dlq_proto_goTypes = nil
210 > file_temporal_server_api_enums_v1_dlq_proto_depIdxs = nil
211 }
go.temporal.io/server/api/enums/v1/fairness_state.pb.go 20 covered LOC · 2 ranges

Open complete file

123 }
124
125 > func init() { file_temporal_server_api_enums_v1_fairness_state_proto_init() } fairness_state.pb.go
126 > func file_temporal_server_api_enums_v1_fairness_state_proto_init() {
127 > if File_temporal_server_api_enums_v1_fairness_state_proto != nil {
128 return
129 }
130 > type x struct{} fairness_state.pb.go
131 > out := protoimpl.TypeBuilder{
132 > File: protoimpl.DescBuilder{
133 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
134 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_fairness_state_proto_rawDesc), len(file_temporal_server_api_enums_v1_fairness_state_proto_rawDesc)),
135 > NumEnums: 1,
136 > NumMessages: 0,
137 > NumExtensions: 0,
138 > NumServices: 0,
139 > },
140 > GoTypes: file_temporal_server_api_enums_v1_fairness_state_proto_goTypes,
141 > DependencyIndexes: file_temporal_server_api_enums_v1_fairness_state_proto_depIdxs,
142 > EnumInfos: file_temporal_server_api_enums_v1_fairness_state_proto_enumTypes,
143 > }.Build()
144 > File_temporal_server_api_enums_v1_fairness_state_proto = out.File
145 > file_temporal_server_api_enums_v1_fairness_state_proto_goTypes = nil
146 > file_temporal_server_api_enums_v1_fairness_state_proto_depIdxs = nil
147 }
go.temporal.io/server/api/enums/v1/replication.pb.go 20 covered LOC · 2 ranges

Open complete file

314 }
315
316 > func init() { file_temporal_server_api_enums_v1_replication_proto_init() } replication.pb.go
317 > func file_temporal_server_api_enums_v1_replication_proto_init() {
318 > if File_temporal_server_api_enums_v1_replication_proto != nil {
319 return
320 }
321 > type x struct{} replication.pb.go
322 > out := protoimpl.TypeBuilder{
323 > File: protoimpl.DescBuilder{
324 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
325 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_replication_proto_rawDesc), len(file_temporal_server_api_enums_v1_replication_proto_rawDesc)),
326 > NumEnums: 3,
327 > NumMessages: 0,
328 > NumExtensions: 0,
329 > NumServices: 0,
330 > },
331 > GoTypes: file_temporal_server_api_enums_v1_replication_proto_goTypes,
332 > DependencyIndexes: file_temporal_server_api_enums_v1_replication_proto_depIdxs,
333 > EnumInfos: file_temporal_server_api_enums_v1_replication_proto_enumTypes,
334 > }.Build()
335 > File_temporal_server_api_enums_v1_replication_proto = out.File
336 > file_temporal_server_api_enums_v1_replication_proto_goTypes = nil
337 > file_temporal_server_api_enums_v1_replication_proto_depIdxs = nil
338 }
go.temporal.io/server/api/errordetails/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

625 }
626
627 > func init() { file_temporal_server_api_errordetails_v1_message_proto_init() } message.pb.go
628 > func file_temporal_server_api_errordetails_v1_message_proto_init() {
629 > if File_temporal_server_api_errordetails_v1_message_proto != nil {
630 return
631 }
632 > type x struct{} message.pb.go
633 > out := protoimpl.TypeBuilder{
634 > File: protoimpl.DescBuilder{
635 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
636 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_errordetails_v1_message_proto_rawDesc), len(file_temporal_server_api_errordetails_v1_message_proto_rawDesc)),
637 > NumEnums: 0,
638 > NumMessages: 10,
639 > NumExtensions: 0,
640 > NumServices: 0,
641 > },
642 > GoTypes: file_temporal_server_api_errordetails_v1_message_proto_goTypes,
643 > DependencyIndexes: file_temporal_server_api_errordetails_v1_message_proto_depIdxs,
644 > MessageInfos: file_temporal_server_api_errordetails_v1_message_proto_msgTypes,
645 > }.Build()
646 > File_temporal_server_api_errordetails_v1_message_proto = out.File
647 > file_temporal_server_api_errordetails_v1_message_proto_goTypes = nil
648 > file_temporal_server_api_errordetails_v1_message_proto_depIdxs = nil
649 }
go.temporal.io/server/api/health/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

300 }
301
302 > func init() { file_temporal_server_api_health_v1_message_proto_init() } message.pb.go
303 > func file_temporal_server_api_health_v1_message_proto_init() {
304 > if File_temporal_server_api_health_v1_message_proto != nil {
305 return
306 }
307 > type x struct{} message.pb.go
308 > out := protoimpl.TypeBuilder{
309 > File: protoimpl.DescBuilder{
310 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
311 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_health_v1_message_proto_rawDesc), len(file_temporal_server_api_health_v1_message_proto_rawDesc)),
312 > NumEnums: 0,
313 > NumMessages: 3,
314 > NumExtensions: 0,
315 > NumServices: 0,
316 > },
317 > GoTypes: file_temporal_server_api_health_v1_message_proto_goTypes,
318 > DependencyIndexes: file_temporal_server_api_health_v1_message_proto_depIdxs,
319 > MessageInfos: file_temporal_server_api_health_v1_message_proto_msgTypes,
320 > }.Build()
321 > File_temporal_server_api_health_v1_message_proto = out.File
322 > file_temporal_server_api_health_v1_message_proto_goTypes = nil
323 > file_temporal_server_api_health_v1_message_proto_depIdxs = nil
324 }
go.temporal.io/server/api/historyservice/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

428 }
429
430 > func init() { file_temporal_server_api_historyservice_v1_service_proto_init() } service.pb.go
431 > func file_temporal_server_api_historyservice_v1_service_proto_init() {
432 > if File_temporal_server_api_historyservice_v1_service_proto != nil {
433 return
434 }
435 > file_temporal_server_api_historyservice_v1_request_response_proto_init() service.pb.go
436 > type x struct{}
437 > out := protoimpl.TypeBuilder{
438 > File: protoimpl.DescBuilder{
439 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
440 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_historyservice_v1_service_proto_rawDesc), len(file_temporal_server_api_historyservice_v1_service_proto_rawDesc)),
441 > NumEnums: 0,
442 > NumMessages: 0,
443 > NumExtensions: 0,
444 > NumServices: 1,
445 > },
446 > GoTypes: file_temporal_server_api_historyservice_v1_service_proto_goTypes,
447 > DependencyIndexes: file_temporal_server_api_historyservice_v1_service_proto_depIdxs,
448 > }.Build()
449 > File_temporal_server_api_historyservice_v1_service_proto = out.File
450 > file_temporal_server_api_historyservice_v1_service_proto_goTypes = nil
451 > file_temporal_server_api_historyservice_v1_service_proto_depIdxs = nil
452 }
go.temporal.io/server/api/matchingservice/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

250 }
251
252 > func init() { file_temporal_server_api_matchingservice_v1_service_proto_init() } service.pb.go
253 > func file_temporal_server_api_matchingservice_v1_service_proto_init() {
254 > if File_temporal_server_api_matchingservice_v1_service_proto != nil {
255 return
256 }
257 > file_temporal_server_api_matchingservice_v1_request_response_proto_init() service.pb.go
258 > type x struct{}
259 > out := protoimpl.TypeBuilder{
260 > File: protoimpl.DescBuilder{
261 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
262 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_matchingservice_v1_service_proto_rawDesc), len(file_temporal_server_api_matchingservice_v1_service_proto_rawDesc)),
263 > NumEnums: 0,
264 > NumMessages: 0,
265 > NumExtensions: 0,
266 > NumServices: 1,
267 > },
268 > GoTypes: file_temporal_server_api_matchingservice_v1_service_proto_goTypes,
269 > DependencyIndexes: file_temporal_server_api_matchingservice_v1_service_proto_depIdxs,
270 > }.Build()
271 > File_temporal_server_api_matchingservice_v1_service_proto = out.File
272 > file_temporal_server_api_matchingservice_v1_service_proto_goTypes = nil
273 > file_temporal_server_api_matchingservice_v1_service_proto_depIdxs = nil
274 }
go.temporal.io/server/api/metrics/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

104 }
105
106 > func init() { file_temporal_server_api_metrics_v1_message_proto_init() } message.pb.go
107 > func file_temporal_server_api_metrics_v1_message_proto_init() {
108 > if File_temporal_server_api_metrics_v1_message_proto != nil {
109 return
110 }
111 > type x struct{} message.pb.go
112 > out := protoimpl.TypeBuilder{
113 > File: protoimpl.DescBuilder{
114 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
115 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_metrics_v1_message_proto_rawDesc), len(file_temporal_server_api_metrics_v1_message_proto_rawDesc)),
116 > NumEnums: 0,
117 > NumMessages: 2,
118 > NumExtensions: 0,
119 > NumServices: 0,
120 > },
121 > GoTypes: file_temporal_server_api_metrics_v1_message_proto_goTypes,
122 > DependencyIndexes: file_temporal_server_api_metrics_v1_message_proto_depIdxs,
123 > MessageInfos: file_temporal_server_api_metrics_v1_message_proto_msgTypes,
124 > }.Build()
125 > File_temporal_server_api_metrics_v1_message_proto = out.File
126 > file_temporal_server_api_metrics_v1_message_proto_goTypes = nil
127 > file_temporal_server_api_metrics_v1_message_proto_depIdxs = nil
128 }
go.temporal.io/server/api/namespace/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

114 }
115
116 > func init() { file_temporal_server_api_namespace_v1_message_proto_init() } message.pb.go
117 > func file_temporal_server_api_namespace_v1_message_proto_init() {
118 > if File_temporal_server_api_namespace_v1_message_proto != nil {
119 return
120 }
121 > type x struct{} message.pb.go
122 > out := protoimpl.TypeBuilder{
123 > File: protoimpl.DescBuilder{
124 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
125 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_namespace_v1_message_proto_rawDesc), len(file_temporal_server_api_namespace_v1_message_proto_rawDesc)),
126 > NumEnums: 0,
127 > NumMessages: 1,
128 > NumExtensions: 0,
129 > NumServices: 0,
130 > },
131 > GoTypes: file_temporal_server_api_namespace_v1_message_proto_goTypes,
132 > DependencyIndexes: file_temporal_server_api_namespace_v1_message_proto_depIdxs,
133 > MessageInfos: file_temporal_server_api_namespace_v1_message_proto_msgTypes,
134 > }.Build()
135 > File_temporal_server_api_namespace_v1_message_proto = out.File
136 > file_temporal_server_api_namespace_v1_message_proto_goTypes = nil
137 > file_temporal_server_api_namespace_v1_message_proto_depIdxs = nil
138 }
go.temporal.io/server/api/persistence/v1/chasm_visibility.pb.go 20 covered LOC · 2 ranges

Open complete file

146 }
147
148 > func init() { file_temporal_server_api_persistence_v1_chasm_visibility_proto_init() } chasm_visibility.pb.go
149 > func file_temporal_server_api_persistence_v1_chasm_visibility_proto_init() {
150 > if File_temporal_server_api_persistence_v1_chasm_visibility_proto != nil {
151 return
152 }
153 > type x struct{} chasm_visibility.pb.go
154 > out := protoimpl.TypeBuilder{
155 > File: protoimpl.DescBuilder{
156 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
157 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_chasm_visibility_proto_rawDesc), len(file_temporal_server_api_persistence_v1_chasm_visibility_proto_rawDesc)),
158 > NumEnums: 0,
159 > NumMessages: 2,
160 > NumExtensions: 0,
161 > NumServices: 0,
162 > },
163 > GoTypes: file_temporal_server_api_persistence_v1_chasm_visibility_proto_goTypes,
164 > DependencyIndexes: file_temporal_server_api_persistence_v1_chasm_visibility_proto_depIdxs,
165 > MessageInfos: file_temporal_server_api_persistence_v1_chasm_visibility_proto_msgTypes,
166 > }.Build()
167 > File_temporal_server_api_persistence_v1_chasm_visibility_proto = out.File
168 > file_temporal_server_api_persistence_v1_chasm_visibility_proto_goTypes = nil
169 > file_temporal_server_api_persistence_v1_chasm_visibility_proto_depIdxs = nil
170 }
go.temporal.io/server/api/persistence/v1/history_tree.pb.go 20 covered LOC · 2 ranges

Open complete file

274 }
275
276 > func init() { file_temporal_server_api_persistence_v1_history_tree_proto_init() } history_tree.pb.go
277 > func file_temporal_server_api_persistence_v1_history_tree_proto_init() {
278 > if File_temporal_server_api_persistence_v1_history_tree_proto != nil {
279 return
280 }
281 > type x struct{} history_tree.pb.go
282 > out := protoimpl.TypeBuilder{
283 > File: protoimpl.DescBuilder{
284 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
285 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_history_tree_proto_rawDesc), len(file_temporal_server_api_persistence_v1_history_tree_proto_rawDesc)),
286 > NumEnums: 0,
287 > NumMessages: 3,
288 > NumExtensions: 0,
289 > NumServices: 0,
290 > },
291 > GoTypes: file_temporal_server_api_persistence_v1_history_tree_proto_goTypes,
292 > DependencyIndexes: file_temporal_server_api_persistence_v1_history_tree_proto_depIdxs,
293 > MessageInfos: file_temporal_server_api_persistence_v1_history_tree_proto_msgTypes,
294 > }.Build()
295 > File_temporal_server_api_persistence_v1_history_tree_proto = out.File
296 > file_temporal_server_api_persistence_v1_history_tree_proto_goTypes = nil
297 > file_temporal_server_api_persistence_v1_history_tree_proto_depIdxs = nil
298 }
go.temporal.io/server/api/persistence/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

846 }
847
848 > func init() { file_temporal_server_api_persistence_v1_tasks_proto_init() } tasks.pb.go
849 > func file_temporal_server_api_persistence_v1_tasks_proto_init() {
850 > if File_temporal_server_api_persistence_v1_tasks_proto != nil {
851 return
852 }
853 > type x struct{} tasks.pb.go
854 > out := protoimpl.TypeBuilder{
855 > File: protoimpl.DescBuilder{
856 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
857 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_tasks_proto_rawDesc), len(file_temporal_server_api_persistence_v1_tasks_proto_rawDesc)),
858 > NumEnums: 0,
859 > NumMessages: 8,
860 > NumExtensions: 0,
861 > NumServices: 0,
862 > },
863 > GoTypes: file_temporal_server_api_persistence_v1_tasks_proto_goTypes,
864 > DependencyIndexes: file_temporal_server_api_persistence_v1_tasks_proto_depIdxs,
865 > MessageInfos: file_temporal_server_api_persistence_v1_tasks_proto_msgTypes,
866 > }.Build()
867 > File_temporal_server_api_persistence_v1_tasks_proto = out.File
868 > file_temporal_server_api_persistence_v1_tasks_proto_goTypes = nil
869 > file_temporal_server_api_persistence_v1_tasks_proto_depIdxs = nil
870 }
go.temporal.io/server/api/token/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

785 }
786
787 > func init() { file_temporal_server_api_token_v1_message_proto_init() } message.pb.go
788 > func file_temporal_server_api_token_v1_message_proto_init() {
789 > if File_temporal_server_api_token_v1_message_proto != nil {
790 return
791 }
792 > type x struct{} message.pb.go
793 > out := protoimpl.TypeBuilder{
794 > File: protoimpl.DescBuilder{
795 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
796 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_token_v1_message_proto_rawDesc), len(file_temporal_server_api_token_v1_message_proto_rawDesc)),
797 > NumEnums: 0,
798 > NumMessages: 7,
799 > NumExtensions: 0,
800 > NumServices: 0,
801 > },
802 > GoTypes: file_temporal_server_api_token_v1_message_proto_goTypes,
803 > DependencyIndexes: file_temporal_server_api_token_v1_message_proto_depIdxs,
804 > MessageInfos: file_temporal_server_api_token_v1_message_proto_msgTypes,
805 > }.Build()
806 > File_temporal_server_api_token_v1_message_proto = out.File
807 > file_temporal_server_api_token_v1_message_proto_goTypes = nil
808 > file_temporal_server_api_token_v1_message_proto_depIdxs = nil
809 }
go.temporal.io/server/api/visibilityservice/v1/request_response.pb.go 20 covered LOC · 2 ranges

Open complete file

402 }
403
404 > func init() { file_temporal_server_api_visibilityservice_v1_request_response_proto_init() } request_response.pb.go
405 > func file_temporal_server_api_visibilityservice_v1_request_response_proto_init() {
406 > if File_temporal_server_api_visibilityservice_v1_request_response_proto != nil {
407 return
408 }
409 > type x struct{} request_response.pb.go
410 > out := protoimpl.TypeBuilder{
411 > File: protoimpl.DescBuilder{
412 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
413 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_visibilityservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_visibilityservice_v1_request_response_proto_rawDesc)),
414 > NumEnums: 0,
415 > NumMessages: 5,
416 > NumExtensions: 0,
417 > NumServices: 0,
418 > },
419 > GoTypes: file_temporal_server_api_visibilityservice_v1_request_response_proto_goTypes,
420 > DependencyIndexes: file_temporal_server_api_visibilityservice_v1_request_response_proto_depIdxs,
421 > MessageInfos: file_temporal_server_api_visibilityservice_v1_request_response_proto_msgTypes,
422 > }.Build()
423 > File_temporal_server_api_visibilityservice_v1_request_response_proto = out.File
424 > file_temporal_server_api_visibilityservice_v1_request_response_proto_goTypes = nil
425 > file_temporal_server_api_visibilityservice_v1_request_response_proto_depIdxs = nil
426 }
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

91 }
92
93 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_service_proto_init() } service.pb.go
94 > func file_temporal_server_chasm_lib_activity_proto_v1_service_proto_init() {
95 > if File_temporal_server_chasm_lib_activity_proto_v1_service_proto != nil {
96 return
97 }
98 > file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_init() service.pb.go
99 > type x struct{}
100 > out := protoimpl.TypeBuilder{
101 > File: protoimpl.DescBuilder{
102 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
103 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_service_proto_rawDesc)),
104 > NumEnums: 0,
105 > NumMessages: 0,
106 > NumExtensions: 0,
107 > NumServices: 1,
108 > },
109 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_service_proto_goTypes,
110 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_service_proto_depIdxs,
111 > }.Build()
112 > File_temporal_server_chasm_lib_activity_proto_v1_service_proto = out.File
113 > file_temporal_server_chasm_lib_activity_proto_v1_service_proto_goTypes = nil
114 > file_temporal_server_chasm_lib_activity_proto_v1_service_proto_depIdxs = nil
115 }
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/service_client.pb.go 20 covered LOC · 4 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) (ActivityServiceClient, error) { service_client.pb.go
40 > resolver, err := monitor.GetResolver(primitives.HistoryService)
41 > if err != nil {
42 return nil, err
43 }
44 > connections := history.NewConnectionPool(resolver, rpcFactory, NewActivityServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) service_client.pb.go
45 > var redirector history.Redirector[ActivityServiceClient]
46 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
47 redirector = history.NewCachingRedirector(
48 connections,
51 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
52 )
53 > } else { service_client.pb.go
54 > redirector = history.NewBasicRedirector(connections, resolver)
55 > }
56 > client := &ActivityServiceLayeredClient{
57 > metricsHandler: metricsHandler,
58 > redirector: redirector,
59 > numShards: config.NumHistoryShards,
60 > retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
61 > }
62 > lc.Append(fx.StopHook(client.Stop))
63 > return client, nil
64 }
65 > func (c *ActivityServiceLayeredClient) Stop() { service_client.pb.go
66 > c.redirector.Close()
67 > }
68 func (c *ActivityServiceLayeredClient) callStartActivityExecutionNoRetry(
69 ctx context.Context,
go.temporal.io/server/chasm/lib/callback/gen/callbackpb/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

148 }
149
150 > func init() { file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_init() } tasks.pb.go
151 > func file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_init() {
152 > if File_temporal_server_chasm_lib_callback_proto_v1_tasks_proto != nil {
153 return
154 }
155 > type x struct{} tasks.pb.go
156 > out := protoimpl.TypeBuilder{
157 > File: protoimpl.DescBuilder{
158 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
159 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_rawDesc)),
160 > NumEnums: 0,
161 > NumMessages: 2,
162 > NumExtensions: 0,
163 > NumServices: 0,
164 > },
165 > GoTypes: file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_goTypes,
166 > DependencyIndexes: file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_depIdxs,
167 > MessageInfos: file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_msgTypes,
168 > }.Build()
169 > File_temporal_server_chasm_lib_callback_proto_v1_tasks_proto = out.File
170 > file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_goTypes = nil
171 > file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_depIdxs = nil
172 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

71 }
72
73 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_init() } service.pb.go
74 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_init() {
75 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto != nil {
76 return
77 }
78 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_init() service.pb.go
79 > type x struct{}
80 > out := protoimpl.TypeBuilder{
81 > File: protoimpl.DescBuilder{
82 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
83 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_rawDesc)),
84 > NumEnums: 0,
85 > NumMessages: 0,
86 > NumExtensions: 0,
87 > NumServices: 1,
88 > },
89 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_goTypes,
90 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_depIdxs,
91 > }.Build()
92 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto = out.File
93 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_goTypes = nil
94 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_depIdxs = nil
95 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/service_client.pb.go 20 covered LOC · 4 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) (NexusOperationServiceClient, error) { service_client.pb.go
40 > resolver, err := monitor.GetResolver(primitives.HistoryService)
41 > if err != nil {
42 return nil, err
43 }
44 > connections := history.NewConnectionPool(resolver, rpcFactory, NewNexusOperationServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) service_client.pb.go
45 > var redirector history.Redirector[NexusOperationServiceClient]
46 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
47 redirector = history.NewCachingRedirector(
48 connections,
51 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
52 )
53 > } else { service_client.pb.go
54 > redirector = history.NewBasicRedirector(connections, resolver)
55 > }
56 > client := &NexusOperationServiceLayeredClient{
57 > metricsHandler: metricsHandler,
58 > redirector: redirector,
59 > numShards: config.NumHistoryShards,
60 > retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
61 > }
62 > lc.Append(fx.StopHook(client.Stop))
63 > return client, nil
64 }
65 > func (c *NexusOperationServiceLayeredClient) Stop() { service_client.pb.go
66 > c.redirector.Close()
67 > }
68 func (c *NexusOperationServiceLayeredClient) callStartNexusOperationNoRetry(
69 ctx context.Context,
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

354 }
355
356 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_init() } tasks.pb.go
357 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_init() {
358 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto != nil {
359 return
360 }
361 > type x struct{} tasks.pb.go
362 > out := protoimpl.TypeBuilder{
363 > File: protoimpl.DescBuilder{
364 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
365 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_rawDesc)),
366 > NumEnums: 0,
367 > NumMessages: 7,
368 > NumExtensions: 0,
369 > NumServices: 0,
370 > },
371 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_goTypes,
372 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_depIdxs,
373 > MessageInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_msgTypes,
374 > }.Build()
375 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto = out.File
376 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_goTypes = nil
377 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_depIdxs = nil
378 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

86 }
87
88 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_init() } service.pb.go
89 > func file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_init() {
90 > if File_temporal_server_chasm_lib_scheduler_proto_v1_service_proto != nil {
91 return
92 }
93 > file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_init() service.pb.go
94 > type x struct{}
95 > out := protoimpl.TypeBuilder{
96 > File: protoimpl.DescBuilder{
97 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
98 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_rawDesc)),
99 > NumEnums: 0,
100 > NumMessages: 0,
101 > NumExtensions: 0,
102 > NumServices: 1,
103 > },
104 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_goTypes,
105 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_depIdxs,
106 > }.Build()
107 > File_temporal_server_chasm_lib_scheduler_proto_v1_service_proto = out.File
108 > file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_goTypes = nil
109 > file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_depIdxs = nil
110 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/service_client.pb.go 20 covered LOC · 4 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) (SchedulerServiceClient, error) { service_client.pb.go
40 > resolver, err := monitor.GetResolver(primitives.HistoryService)
41 > if err != nil {
42 return nil, err
43 }
44 > connections := history.NewConnectionPool(resolver, rpcFactory, NewSchedulerServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) service_client.pb.go
45 > var redirector history.Redirector[SchedulerServiceClient]
46 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
47 redirector = history.NewCachingRedirector(
48 connections,
51 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
52 )
53 > } else { service_client.pb.go
54 > redirector = history.NewBasicRedirector(connections, resolver)
55 > }
56 > client := &SchedulerServiceLayeredClient{
57 > metricsHandler: metricsHandler,
58 > redirector: redirector,
59 > numShards: config.NumHistoryShards,
60 > retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
61 > }
62 > lc.Append(fx.StopHook(client.Stop))
63 > return client, nil
64 }
65 > func (c *SchedulerServiceLayeredClient) Stop() { service_client.pb.go
66 > c.redirector.Close()
67 > }
68 func (c *SchedulerServiceLayeredClient) callCreateScheduleNoRetry(
69 ctx context.Context,
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

343 }
344
345 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_init() } tasks.pb.go
346 > func file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_init() {
347 > if File_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto != nil {
348 return
349 }
350 > type x struct{} tasks.pb.go
351 > out := protoimpl.TypeBuilder{
352 > File: protoimpl.DescBuilder{
353 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
354 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_rawDesc)),
355 > NumEnums: 0,
356 > NumMessages: 7,
357 > NumExtensions: 0,
358 > NumServices: 0,
359 > },
360 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_goTypes,
361 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_depIdxs,
362 > MessageInfos: file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_msgTypes,
363 > }.Build()
364 > File_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto = out.File
365 > file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_goTypes = nil
366 > file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_depIdxs = nil
367 }
go.temporal.io/server/chasm/lib/tests/gen/testspb/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

242 }
243
244 > func init() { file_temporal_server_chasm_lib_tests_proto_v1_message_proto_init() } message.pb.go
245 > func file_temporal_server_chasm_lib_tests_proto_v1_message_proto_init() {
246 > if File_temporal_server_chasm_lib_tests_proto_v1_message_proto != nil {
247 return
248 }
249 > type x struct{} message.pb.go
250 > out := protoimpl.TypeBuilder{
251 > File: protoimpl.DescBuilder{
252 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
253 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_tests_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_tests_proto_v1_message_proto_rawDesc)),
254 > NumEnums: 0,
255 > NumMessages: 4,
256 > NumExtensions: 0,
257 > NumServices: 0,
258 > },
259 > GoTypes: file_temporal_server_chasm_lib_tests_proto_v1_message_proto_goTypes,
260 > DependencyIndexes: file_temporal_server_chasm_lib_tests_proto_v1_message_proto_depIdxs,
261 > MessageInfos: file_temporal_server_chasm_lib_tests_proto_v1_message_proto_msgTypes,
262 > }.Build()
263 > File_temporal_server_chasm_lib_tests_proto_v1_message_proto = out.File
264 > file_temporal_server_chasm_lib_tests_proto_v1_message_proto_goTypes = nil
265 > file_temporal_server_chasm_lib_tests_proto_v1_message_proto_depIdxs = nil
266 }
go.temporal.io/server/chasm/lib/tests/gen/testspb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

46 }
47
48 > func init() { file_temporal_server_chasm_lib_tests_proto_v1_service_proto_init() } service.pb.go
49 > func file_temporal_server_chasm_lib_tests_proto_v1_service_proto_init() {
50 > if File_temporal_server_chasm_lib_tests_proto_v1_service_proto != nil {
51 return
52 }
53 > file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_init() service.pb.go
54 > type x struct{}
55 > out := protoimpl.TypeBuilder{
56 > File: protoimpl.DescBuilder{
57 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
58 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_tests_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_tests_proto_v1_service_proto_rawDesc)),
59 > NumEnums: 0,
60 > NumMessages: 0,
61 > NumExtensions: 0,
62 > NumServices: 1,
63 > },
64 > GoTypes: file_temporal_server_chasm_lib_tests_proto_v1_service_proto_goTypes,
65 > DependencyIndexes: file_temporal_server_chasm_lib_tests_proto_v1_service_proto_depIdxs,
66 > }.Build()
67 > File_temporal_server_chasm_lib_tests_proto_v1_service_proto = out.File
68 > file_temporal_server_chasm_lib_tests_proto_v1_service_proto_goTypes = nil
69 > file_temporal_server_chasm_lib_tests_proto_v1_service_proto_depIdxs = nil
70 }
go.temporal.io/server/chasm/lib/workflow/gen/workflowpb/v1/state.pb.go 20 covered LOC · 2 ranges

Open complete file

211 }
212
213 > func init() { file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_init() } state.pb.go
214 > func file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_init() {
215 > if File_temporal_server_chasm_lib_workflow_proto_v1_state_proto != nil {
216 return
217 }
218 > type x struct{} state.pb.go
219 > out := protoimpl.TypeBuilder{
220 > File: protoimpl.DescBuilder{
221 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
222 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_rawDesc), len(file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_rawDesc)),
223 > NumEnums: 0,
224 > NumMessages: 3,
225 > NumExtensions: 0,
226 > NumServices: 0,
227 > },
228 > GoTypes: file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_goTypes,
229 > DependencyIndexes: file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_depIdxs,
230 > MessageInfos: file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_msgTypes,
231 > }.Build()
232 > File_temporal_server_chasm_lib_workflow_proto_v1_state_proto = out.File
233 > file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_goTypes = nil
234 > file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_depIdxs = nil
235 }
go.temporal.io/server/chasm/lib/workflow/gen/workflowpb/v1/update_state.pb.go 20 covered LOC · 2 ranges

Open complete file

113 }
114
115 > func init() { file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_init() } update_state.pb.go
116 > func file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_init() {
117 > if File_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto != nil {
118 return
119 }
120 > type x struct{} update_state.pb.go
121 > out := protoimpl.TypeBuilder{
122 > File: protoimpl.DescBuilder{
123 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
124 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_rawDesc), len(file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_rawDesc)),
125 > NumEnums: 0,
126 > NumMessages: 1,
127 > NumExtensions: 0,
128 > NumServices: 0,
129 > },
130 > GoTypes: file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_goTypes,
131 > DependencyIndexes: file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_depIdxs,
132 > MessageInfos: file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_msgTypes,
133 > }.Build()
134 > File_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto = out.File
135 > file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_goTypes = nil
136 > file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_depIdxs = nil
137 }
go.temporal.io/server/chasm/lib/workflow/nexus_service.go 20 covered LOC · 3 ranges

Open complete file

60 func mustNewWorkflowServiceNexusHandler(
61 handler *workflowServiceNexusHandler,
62 > ) *nexus.Service { nexus_service.go
63 > svc := nexus.NewService(workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.ServiceName)
64 > svc.MustRegister(nexus.NewSyncOperation(
65 > workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.SignalWithStartWorkflowExecution.Name(),
66 > handler.signalWithStartWorkflowExecution,
67 > ))
68 > return svc
69 > }
70
71 > func (h *workflowServiceNexusHandler) setHistoryHandler(handler historyservice.HistoryServiceServer) { nexus_service.go
72 > h.historyHandler = handler
73 > }
74
75 type SignalWithStartOperationProcessor struct {
127 saMapperProvider searchattribute.MapperProvider,
128 saValidator *searchattribute.Validator,
129 > ) *chasm.NexusServiceProcessor { nexus_service.go
130 > sp := chasm.NewNexusServiceProcessor(workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.ServiceName)
131 > op := SignalWithStartOperationProcessor{validator: NewValidator(config, saMapperProvider, saValidator)}
132 > sp.MustRegisterOperation(
133 > workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.SignalWithStartWorkflowExecution.Name(),
134 > chasm.NewRegisterableNexusOperationProcessor(op),
135 > )
136 > return sp
137 > }
go.temporal.io/server/client/history/client.go 20 covered LOC · 4 ranges

Open complete file

52 rpcFactory RPCFactory,
53 timeout time.Duration,
54 > ) historyservice.HistoryServiceClient { client.go
55 > connections := NewConnectionPool(historyServiceResolver, rpcFactory, historyservice.NewHistoryServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc))
56 >
57 > var redirector Redirector[historyservice.HistoryServiceClient]
58 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
59 logger.Info("historyClient: ownership caching enabled")
60 redirector = NewCachingRedirector(
64 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
65 )
66 > } else { client.go
67 > logger.Info("historyClient: ownership caching disabled")
68 > redirector = NewBasicRedirector(connections, historyServiceResolver)
69 > }
70
71 > return &clientImpl{ client.go
72 > connections: connections,
73 > logger: logger,
74 > numberOfShards: numberOfShards,
75 > redirector: redirector,
76 > timeout: timeout,
77 > tokenSerializer: tasktoken.NewSerializer(),
78 > }
79 }
80
294
295 // Stop stops the membership watcher and closes pooled connections.
296 > func (c *clientImpl) Stop() { client.go
297 > c.redirector.Close()
298 > }
299
300 func checkShardID(shardID int32) error {
go.temporal.io/server/common/channel/shutdown_once.go 20 covered LOC · 4 ranges

Open complete file

26 )
27
28 > func NewShutdownOnce() *ShutdownOnceImpl { shutdown_once.go
29 > return &ShutdownOnceImpl{
30 > status: shutdownOnceStatusOpen,
31 > channel: make(chan struct{}),
32 > }
33 > }
34
35 > func (c *ShutdownOnceImpl) Shutdown() { shutdown_once.go
36 > if atomic.CompareAndSwapInt32(
37 > &c.status,
38 > shutdownOnceStatusOpen,
39 > shutdownOnceStatusClosed,
40 > ) {
41 > close(c.channel)
42 > }
43 }
44
45 > func (c *ShutdownOnceImpl) IsShutdown() bool { shutdown_once.go
46 > return atomic.LoadInt32(&c.status) == shutdownOnceStatusClosed
47 > }
48
49 > func (c *ShutdownOnceImpl) Channel() <-chan struct{} { shutdown_once.go
50 > return c.channel
51 > }
go.temporal.io/server/common/client_cache.go 20 covered LOC · 3 ranges

Open complete file

52 clientProvider clientProvider,
53 logger log.Logger,
54 > ) ClientCache { client_cache.go
55 >
56 > return &clientCacheImpl{
57 > keyResolver: keyResolver,
58 > clientProvider: clientProvider,
59 >
60 > clients: make(map[string]cachedEntry),
61 > logger: logger,
62 > }
63 > }
64
65 > func (c *clientCacheImpl) Lookup(key string, index int) (string, error) { client_cache.go
66 > return c.keyResolver.Lookup(key, index)
67 > }
68
69 func (c *clientCacheImpl) GetClientForKey(key string, index int) (any, error) {
131 }
132
133 > func (c *clientCacheImpl) EvictAll() { client_cache.go
134 > c.cacheLock.Lock()
135 > entries := c.clients
136 > c.clients = make(map[string]cachedEntry)
137 > c.cacheLock.Unlock()
138 >
139 > for _, entry := range entries {
140 if entry.release != nil {
141 if err := entry.release(); err != nil {
go.temporal.io/server/common/util/wildcard.go 20 covered LOC · 7 ranges

Open complete file

18 // WildCardStringToRegexps converts a given slices of string patterns to a slice of regular expressions matching
19 // wildcards (*) with any substring.
20 > func WildCardStringsToRegexp(patterns []string) (*regexp.Regexp, error) { wildcard.go
21 > var result strings.Builder
22 > result.WriteRune('^')
23 > for i, pattern := range patterns {
24 > result.WriteRune('(')
25 > first := true
26 > for literal := range strings.SplitSeq(pattern, "*") {
27 > if !first {
28 // Replace * with .*
29 result.WriteString(".*")
30 }
31 > result.WriteString(regexp.QuoteMeta(literal)) wildcard.go
32 > first = false
33 }
34 > result.WriteRune(')') wildcard.go
35 > if i < len(patterns)-1 {
36 > result.WriteRune('|') wildcard.go
37 > }
38 }
39 > result.WriteRune('$') wildcard.go
40 > return regexp.Compile(result.String())
41 }
42
43 // MustWildCardStringsToRegexp is like WildCardStringsToRegexp but panics on error.
44 > func MustWildCardStringsToRegexp(patterns []string) *regexp.Regexp { wildcard.go
45 > re, err := WildCardStringsToRegexp(patterns)
46 > if err != nil {
47 panic(err) //nolint:forbidigo // Must* functions conventionally panic on error.
48 }
49 > return re wildcard.go
50 }
go.temporal.io/server/service/history/outbound_queue_active_task_executor.go 20 covered LOC · 1 range

Open complete file

41 chasmEngine chasm.Engine,
42 matchingClient resource.MatchingClient,
43 > ) *outboundQueueActiveTaskExecutor { outbound_queue_active_task_executor.go
44 > scopedMetricsHandler := metricsHandler.WithTags(
45 > metrics.OperationTag(metrics.OperationOutboundQueueProcessorScope),
46 > )
47 > return &outboundQueueActiveTaskExecutor{
48 > stateMachineEnvironment: stateMachineEnvironment{
49 > shardContext: shardCtx,
50 > cache: workflowCache,
51 > logger: logger,
52 > metricsHandler: scopedMetricsHandler,
53 > },
54 > chasmEngine: chasmEngine,
55 > workerCommandsDispatcher: workercommands.NewDispatcher(
56 > matchingClient,
57 > shardCtx.GetConfig(),
58 > scopedMetricsHandler,
59 > logger,
60 > ),
61 > }
62 > }
63
64 func (e *outboundQueueActiveTaskExecutor) Execute(
go.temporal.io/server/service/history/shard/ownership_based_quota_scaler.go 20 covered LOC · 4 ranges

Open complete file

62 totalNumShards int,
63 updateAppliedCallback chan struct{},
64 > ) (*OwnershipBasedQuotaScalerImpl, error) { ownership_based_quota_scaler.go
65 > if totalNumShards <= 0 {
66 return nil, fmt.Errorf("%w: %d", ErrNonPositiveTotalNumShards, totalNumShards)
67 }
68
69 > scaler := &OwnershipBasedQuotaScalerImpl{ ownership_based_quota_scaler.go
70 > shardCounter: shardCounter,
71 > totalNumShards: totalNumShards,
72 > updateAppliedCallback: updateAppliedCallback,
73 > subscription: shardCounter.SubscribeShardCount(),
74 > }
75 >
76 > scaler.shardCount.Store(shardCountNotSet)
77 > scaler.shutdownWG.Go(func() {
78 >
79 > for count := range scaler.subscription.ShardCount() {
80 > scaler.shardCount.Store(int64(count))
81 > if scaler.updateAppliedCallback != nil {
82 scaler.updateAppliedCallback <- struct{}{}
83 }
97 }
98
99 > func (s *OwnershipBasedQuotaScalerImpl) Close() { ownership_based_quota_scaler.go
100 > s.subscription.Unsubscribe()
101 > s.shutdownWG.Wait()
102 > }
103
104 func (s LazyLoadedOwnershipBasedQuotaScaler) ScaleFactor() (float64, bool) {
go.temporal.io/server/chasm/lib/workflow/registry.go 19 covered LOC · 10 ranges

Open complete file

30
31 // NewRegistry creates a new [Registry].
32 > func NewRegistry() *Registry { registry.go
33 > return &Registry{
34 > commandHandlers: make(map[enumspb.CommandType]CommandHandler),
35 > eventDefinitions: make(map[enumspb.EventType]EventDefinition),
36 > eventDefinitionsByGoType: make(map[reflect.Type]EventDefinition),
37 > }
38 > }
39
40 // Register registers all command handlers and event definitions from a [Library].
41 // Returns an [ErrDuplicateRegistration] if a handler or definition is already registered.
42 // All registration is expected to happen in a single thread on process initialization.
43 > func (r *Registry) Register(lib Library) error { registry.go
44 > for t, handler := range lib.CommandHandlers() {
45 > if existing, ok := r.commandHandlers[t]; ok { registry.go
46 return fmt.Errorf("%w: command handler for %v: %v", ErrDuplicateRegistration, t, existing)
47 }
48 > r.commandHandlers[t] = handler registry.go
49 }
50 > for _, def := range lib.EventDefinitions() { registry.go
51 > if existing, ok := r.eventDefinitions[def.Type()]; ok { registry.go
52 return fmt.Errorf("%w: event handler for %v: %v", ErrDuplicateRegistration, def.Type(), existing)
53 }
54 > goType := reflect.TypeOf(def) registry.go
55 > for goType.Kind() == reflect.Pointer {
56 goType = goType.Elem()
57 }
58 > if existing, ok := r.eventDefinitionsByGoType[goType]; ok { registry.go
59 return fmt.Errorf("%w: event definition for Go type %v: %v", ErrDuplicateRegistration, goType, existing)
60 }
61 > r.eventDefinitions[def.Type()] = def registry.go
62 > r.eventDefinitionsByGoType[goType] = def
63 }
64 > return nil registry.go
65 }
66
go.temporal.io/server/common/finalizer/finalizer.go 19 covered LOC · 5 ranges

Open complete file

31 logger log.Logger,
32 metricsHandler metrics.Handler,
33 > ) *Finalizer { finalizer.go
34 > return &Finalizer{
35 > logger: logger,
36 > metricsHandler: metricsHandler,
37 > callbacks: make(map[string]func(context.Context) error),
38 > }
39 > }
40
41 // Register adds a callback to the finalizer.
85 func (f *Finalizer) Run(
86 timeout time.Duration,
87 > ) int { finalizer.go
88 > if timeout == 0 {
89 f.logger.Debug("finalizer skipped: zero timeout")
90 return 0
91 }
92
93 > f.mu.Lock() finalizer.go
94 > if f.finalized {
95 f.logger.Warn("finalizer skipped: called more than once")
96 f.mu.Unlock()
97 return 0
98 }
99 > f.finalized = true finalizer.go
100 > f.mu.Unlock() // unlocking immediately to unblock any calls to Register/Deregister
101 >
102 > totalCount := len(f.callbacks)
103 > if totalCount == 0 {
104 > f.logger.Debug("finalizer skipped: no callbacks") finalizer.go
105 > return 0
106 > }
107
108 f.logger.Debug("finalizer starting",
go.temporal.io/server/common/persistence/namespace_replication_queue.go 19 covered LOC · 4 ranges

Open complete file

28 metricsHandler metrics.Handler,
29 logger log.Logger,
30 > ) (NamespaceReplicationQueue, error) { namespace_replication_queue.go
31 >
32 > blob, err := serializer.QueueMetadataToBlob(
33 > &persistencespb.QueueMetadata{
34 > ClusterAckLevels: make(map[string]int64),
35 > })
36 > if err != nil {
37 return nil, err
38 }
39 > err = queue.Init(context.TODO(), blob) namespace_replication_queue.go
40 > if err != nil {
41 return nil, err
42 }
43
44 > return &namespaceReplicationQueueImpl{ namespace_replication_queue.go
45 > queue: queue,
46 > clusterName: clusterName,
47 > metricsHandler: metricsHandler,
48 > logger: logger,
49 > serializer: serializer,
50 > }, nil
51 }
52
89 )
90
91 > func (q *namespaceReplicationQueueImpl) Close() { namespace_replication_queue.go
92 > q.queue.Close()
93 > }
94
95 func (q *namespaceReplicationQueueImpl) Publish(ctx context.Context, task *replicationspb.ReplicationTask) error {
go.temporal.io/server/common/rpc/interceptor/health_check.go 19 covered LOC · 3 ranges

Open complete file

116
117 // NewHealthCheckInterceptor creates a new health check interceptor
118 > func NewHealthCheckInterceptor(healthSignalAggregator HealthSignalAggregator) *HealthCheckInterceptor { health_check.go
119 > return &HealthCheckInterceptor{
120 > healthSignalAggregator: healthSignalAggregator,
121 > }
122 > }
123
124 // UnaryIntercept implements the gRPC unary interceptor interface
176 latencyWindowSize time.Duration,
177 latencyWindowCount int,
178 > ) *healthSignalAggregatorImpl { health_check.go
179 > latencyDistribution, err := stats.NewWindowedTDigest(stats.WindowConfig{
180 > WindowSize: latencyWindowSize,
181 > WindowCount: latencyWindowCount,
182 > })
183 > if err != nil {
184 logger.Error("failed to create latency distribution helper, falling back to default config", tag.Error(err))
185 latencyDistribution, err = stats.NewWindowedTDigest(stats.WindowConfig{
192 }
193
194 > return &healthSignalAggregatorImpl{ health_check.go
195 > logger: logger,
196 > aggregatorEnabled: aggregatorEnabled,
197 > percentilesEnabled: percentilesEnabled,
198 > latencyAverage: aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize),
199 > latencyDistribution: latencyDistribution,
200 > errorRatio: aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize),
201 > }
202 }
203
go.temporal.io/server/service/history/events/cache.go 19 covered LOC · 3 ranges

Open complete file

60 logger log.Logger,
61 disabled bool,
62 > ) Cache { cache.go
63 > return newEventsCache(executionManager, handler, logger, config.EventsHostLevelCacheMaxSizeBytes(), config.EventsCacheTTL(), disabled)
64 > }
65
66 func NewShardLevelEventsCache(
70 logger log.Logger,
71 disabled bool,
72 > ) Cache { cache.go
73 > return newEventsCache(executionManager, handler, logger, config.EventsShardLevelCacheMaxSizeBytes(), config.EventsCacheTTL(), disabled)
74 > }
75
76 func newEventsCache(
81 ttl time.Duration,
82 disabled bool,
83 > ) *CacheImpl { cache.go
84 > opts := &cache.Options{}
85 > opts.TTL = ttl
86 >
87 > taggedMetricHandler := metricsHandler.WithTags(metrics.CacheTypeTag(metrics.EventsCacheTypeTagValue))
88 > return &CacheImpl{
89 > Cache: cache.NewWithMetrics(maxSize, opts, taggedMetricHandler),
90 > executionManager: executionManager,
91 > metricsHandler: taggedMetricHandler,
92 > logger: logger,
93 > disabled: disabled,
94 > }
95 > }
96
97 func (e *CacheImpl) validateKey(key EventKey) bool {
go.temporal.io/server/service/history/queues/range.go 19 covered LOC · 7 ranges

Open complete file

17 inclusiveMin tasks.Key,
18 exclusiveMax tasks.Key,
19 > ) Range { range.go
20 > if inclusiveMin.CompareTo(exclusiveMax) > 0 {
21 panic(fmt.Sprintf("invalid task range, min %v is larger than max %v", inclusiveMin, exclusiveMax))
22 }
23
24 > return Range{ range.go
25 > InclusiveMin: inclusiveMin,
26 > ExclusiveMax: exclusiveMax,
27 > }
28 }
29
30 > func (r *Range) IsEmpty() bool { range.go
31 > return r.InclusiveMin.CompareTo(r.ExclusiveMax) == 0
32 > }
33
34 func (r *Range) ContainsKey(
35 key tasks.Key,
36 > ) bool { range.go
37 > return key.CompareTo(r.InclusiveMin) >= 0 &&
38 > key.CompareTo(r.ExclusiveMax) < 0
39 > }
40
41 func (r *Range) ContainsRange(
48 func (r *Range) CanSplit(
49 key tasks.Key,
50 > ) bool { range.go
51 > return r.ContainsKey(key) || r.ExclusiveMax.CompareTo(key) == 0
52 > }
53
54 func (r *Range) Split(
55 key tasks.Key,
56 > ) (left Range, right Range) { range.go
57 > if !r.CanSplit(key) {
58 panic(fmt.Sprintf("Unable to split range %v at %v", r, key))
59 }
60
61 > return NewRange(r.InclusiveMin, key), NewRange(key, r.ExclusiveMax) range.go
62 }
63
go.temporal.io/server/service/history/tasks/task_category_registry.go 19 covered LOC · 3 ranges

Open complete file

26 // each entry point that uses it. Essentially, get it from the dependency graph instead of calling this method, unless
27 // you're in a test.
28 > func NewDefaultTaskCategoryRegistry() *MutableTaskCategoryRegistry { task_category_registry.go
29 > return &MutableTaskCategoryRegistry{
30 > categories: map[int]Category{
31 > CategoryTransfer.ID(): CategoryTransfer,
32 > CategoryTimer.ID(): CategoryTimer,
33 > CategoryVisibility.ID(): CategoryVisibility,
34 > CategoryReplication.ID(): CategoryReplication,
35 > CategoryMemoryTimer.ID(): CategoryMemoryTimer,
36 > CategoryOutbound.ID(): CategoryOutbound,
37 > },
38 > }
39 > }
40
41 // AddCategory register a Category with the registry or panics if a Category with the same ID has already been
55
56 // GetCategoryByID returns a registered Category with the same ID from the registry or false if no such Category exists.
57 > func (r *MutableTaskCategoryRegistry) GetCategoryByID(id int) (Category, bool) { task_category_registry.go
58 > category, ok := r.categories[id]
59 > return category, ok
60 > }
61
62 // GetCategories returns a deep copy of all registered Category objects from the registry.
63 > func (r *MutableTaskCategoryRegistry) GetCategories() map[int]Category { task_category_registry.go
64 > return maps.Clone(r.categories)
65 > }
go.temporal.io/server/chasm/lib/scheduler/invoker_tasks.go 18 covered LOC · 2 ranges

Open complete file

101 )
102
103 > func NewInvokerExecuteTaskHandler(opts InvokerTaskHandlerOptions) *InvokerExecuteTaskHandler { invoker_tasks.go
104 > return &InvokerExecuteTaskHandler{
105 > config: opts.Config,
106 > metricsHandler: opts.MetricsHandler,
107 > baseLogger: opts.BaseLogger,
108 > historyClient: opts.HistoryClient,
109 > frontendClient: opts.FrontendClient,
110 > }
111 > }
112
113 > func NewInvokerProcessBufferTaskHandler(opts InvokerTaskHandlerOptions) *InvokerProcessBufferTaskHandler { invoker_tasks.go
114 > return &InvokerProcessBufferTaskHandler{
115 > config: opts.Config,
116 > metricsHandler: opts.MetricsHandler,
117 > baseLogger: opts.BaseLogger,
118 > historyClient: opts.HistoryClient,
119 > frontendClient: opts.FrontendClient,
120 > }
121 > }
122
123 // recordDuplicateExecuteDrops emits a metric + Debug log for CompletedStarts
go.temporal.io/server/common/aggregate/moving_window_average.go 18 covered LOC · 2 ranges

Open complete file

32 windowSize time.Duration,
33 maxBufferSize int,
34 > ) *MovingWindowAvgImpl { moving_window_average.go
35 > return &MovingWindowAvgImpl{
36 > windowSize: windowSize,
37 > maxBufferSize: maxBufferSize,
38 > buffer: make([]timestampedData, maxBufferSize),
39 > }
40 > }
41
42 > func (a *MovingWindowAvgImpl) Record(val int64) { moving_window_average.go
43 > a.Lock()
44 > defer a.Unlock()
45 >
46 > a.buffer[a.tailIdx] = timestampedData{timestamp: time.Now(), value: val}
47 > a.tailIdx = (a.tailIdx + 1) % a.maxBufferSize
48 >
49 > a.sum += val
50 > a.count++
51 >
52 > if a.tailIdx == a.headIdx {
53 // buffer full, expire oldest element
54 a.sum -= a.buffer[a.headIdx].value
go.temporal.io/server/common/dynamicconfig/gradual_change.go 18 covered LOC · 6 ranges

Open complete file

25 // StaticGradualChange returns a GradualChange whose Value always returns def and whose When
26 // always returns a time in the past.
27 > func StaticGradualChange[T any](def T) GradualChange[T] { gradual_change.go
28 > return GradualChange[T]{New: def}
29 > }
30
31 // Value returns the value for the given key at the given time.
32 > func (c *GradualChange[T]) Value(key []byte, now time.Time) T { gradual_change.go
33 > if !now.Before(c.End) {
34 > return c.New gradual_change.go
35 > } else if !now.After(c.Start) { gradual_change.go
36 return c.Old
37 }
56 // of type GradualChange into a GradualChange.
57 // nolint:revive // cognitive-complexity // this looks complicated but each case is fairly simple
58 > func ConvertGradualChange[T any](def T) func(v any) (GradualChange[T], error) { gradual_change.go
59 > changeConverter := ConvertStructure(StaticGradualChange(def))
60 >
61 > // Call this once so that if it's going to panic, it panics at static init time.
62 > _, _ = changeConverter(nil)
63 >
64 > switch reflect.TypeFor[T]() {
65 > case reflect.TypeFor[bool]():
66 > return func(v any) (GradualChange[T], error) {
67 if b, err := convertBool(v); err == nil {
68 var change GradualChange[T]
72 return changeConverter(v)
73 }
74 > case reflect.TypeFor[int](): gradual_change.go
75 > return func(v any) (GradualChange[T], error) {
76 if i, err := convertInt(v); err == nil {
77 var change GradualChange[T]
go.temporal.io/server/common/rpc/multistats.go 18 covered LOC · 4 ranges

Open complete file

10 type MultiStatsHandler []stats.Handler
11
12 > func (m MultiStatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { multistats.go
13 > for _, h := range m {
14 > ctx = h.TagConn(ctx, info)
15 > }
16 > return ctx
17 }
18
19 > func (m MultiStatsHandler) HandleConn(ctx context.Context, cs stats.ConnStats) { multistats.go
20 > for _, h := range m {
21 > h.HandleConn(ctx, cs)
22 > }
23 }
24
25 > func (m MultiStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { multistats.go
26 > for _, h := range m {
27 > ctx = h.TagRPC(ctx, info)
28 > }
29 > return ctx
30 }
31
32 > func (m MultiStatsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { multistats.go
33 > for _, h := range m {
34 > h.HandleRPC(ctx, rs)
35 > }
36 }
go.temporal.io/server/common/tasks/rate_limited_scheduler.go 18 covered LOC · 3 ranges

Open complete file

44 logger log.Logger,
45 metricsHandler metrics.Handler,
46 > ) *RateLimitedScheduler[T] { rate_limited_scheduler.go
47 > return &RateLimitedScheduler[T]{
48 > scheduler: scheduler,
49 > rateLimiter: rateLimiter,
50 > timeSource: timeSource,
51 > quotaRequestFn: quotaRequestFn,
52 > metricTagsFn: metricTagsFn,
53 > options: options,
54 > logger: logger,
55 > metricsHandler: metricsHandler,
56 > }
57 > }
58
59 func (s *RateLimitedScheduler[T]) Submit(task T) {
73 }
74
75 > func (s *RateLimitedScheduler[T]) Start() { rate_limited_scheduler.go
76 > s.scheduler.Start()
77 > }
78
79 > func (s *RateLimitedScheduler[T]) Stop() { rate_limited_scheduler.go
80 > s.scheduler.Stop()
81 > }
82
83 func (s *RateLimitedScheduler[T]) wait(task T) {
go.temporal.io/server/components/nexusoperations/config.go 18 covered LOC · 1 range

Open complete file

185 }
186
187 > func ConfigProvider(dc *dynamicconfig.Collection, cfg *config.Persistence) *Config { config.go
188 > return &Config{
189 > RequestTimeout: RequestTimeout.Get(dc),
190 > MinRequestTimeout: MinRequestTimeout.Get(dc),
191 > MaxConcurrentOperations: MaxConcurrentOperations.Get(dc),
192 > MaxServiceNameLength: MaxServiceNameLength.Get(dc),
193 > MaxOperationNameLength: MaxOperationNameLength.Get(dc),
194 > MaxOperationTokenLength: MaxOperationTokenLength.Get(dc),
195 > MaxOperationHeaderSize: MaxOperationHeaderSize.Get(dc),
196 > DisallowedOperationHeaders: DisallowedOperationHeaders.Get(dc),
197 > MaxOperationScheduleToCloseTimeout: MaxOperationScheduleToCloseTimeout.Get(dc),
198 > PayloadSizeLimit: dynamicconfig.BlobSizeLimitError.Get(dc),
199 > CallbackURLTemplate: CallbackURLTemplate.Get(dc),
200 > UseSystemCallbackURL: UseSystemCallbackURL.Get(dc),
201 > UseNewFailureWireFormat: chasmnexus.UseNewFailureWireFormat.Get(dc),
202 > RecordCancelRequestCompletionEvents: RecordCancelRequestCompletionEvents.Get(dc),
203 > MetricTagConfig: MetricTagConfiguration.Get(dc),
204 > RetryPolicy: func() backoff.RetryPolicy {
205 return backoff.NewExponentialRetryPolicy(
206 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/service/history/chasm_engine.go 18 covered LOC · 3 ranges

Open complete file

72 fx.Provide(NewChasmNotifier),
73 fx.Provide(newChasmEngine),
74 > fx.Provide(func(impl *ChasmEngine) chasm.Engine { return impl }), chasm_engine.go
75 > fx.Invoke(func(impl *ChasmEngine, shardController shard.Controller) {
76 > impl.SetShardController(shardController)
77 > }),
78 )
79
86 historyServiceResolver membership.ServiceResolver,
87 hostInfoProvider membership.HostInfoProvider,
88 > ) *ChasmEngine { chasm_engine.go
89 > return &ChasmEngine{
90 > executionCache: executionCache,
91 > registry: registry,
92 > config: config,
93 > notifier: notifier,
94 > logger: logger,
95 > historyServiceResolver: historyServiceResolver,
96 > hostInfoProvider: hostInfoProvider,
97 > }
98 > }
99
100 // This is for breaking fx cycle dependency.
102 func (e *ChasmEngine) SetShardController(
103 shardController shard.Controller,
104 > ) { chasm_engine.go
105 > e.shardController = shardController
106 > }
107
108 func (e *ChasmEngine) NotifyExecution(key chasm.ExecutionKey) {
go.temporal.io/server/chasm/lib/activity/activity_tasks.go 17 covered LOC · 5 ranges

Open complete file

24 }
25
26 > func newActivityDispatchTaskHandler(opts activityDispatchTaskHandlerOptions) *activityDispatchTaskHandler { activity_tasks.go
27 > return &activityDispatchTaskHandler{
28 > opts: opts,
29 > }
30 > }
31
32 func (h *activityDispatchTaskHandler) Validate(
83 }
84
85 > func newScheduleToStartTimeoutTaskHandler() *scheduleToStartTimeoutTaskHandler { activity_tasks.go
86 > return &scheduleToStartTimeoutTaskHandler{}
87 > }
88
89 func (h *scheduleToStartTimeoutTaskHandler) Validate(
119 type scheduleToCloseTimeoutTaskHandler struct{ chasm.PureTaskHandlerBase }
120
121 > func newScheduleToCloseTimeoutTaskHandler() *scheduleToCloseTimeoutTaskHandler { activity_tasks.go
122 > return &scheduleToCloseTimeoutTaskHandler{}
123 > }
124
125 func (h *scheduleToCloseTimeoutTaskHandler) Validate(
165 type startToCloseTimeoutTaskHandler struct{ chasm.PureTaskHandlerBase }
166
167 > func newStartToCloseTimeoutTaskHandler() *startToCloseTimeoutTaskHandler { activity_tasks.go
168 > return &startToCloseTimeoutTaskHandler{}
169 > }
170
171 func (h *startToCloseTimeoutTaskHandler) Validate(
215 type heartbeatTimeoutTaskHandler struct{ chasm.PureTaskHandlerBase }
216
217 > func newHeartbeatTimeoutTaskHandler() *heartbeatTimeoutTaskHandler { activity_tasks.go
218 > return &heartbeatTimeoutTaskHandler{}
219 > }
220
221 // Validate validates a HeartbeatTimeoutTask.
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/queue.go 17 covered LOC · 4 ranges

Open complete file

107 ctx context.Context,
108 row *sqlplugin.QueueMetadataRow,
109 > ) (sql.Result, error) { queue.go
110 > return mdb.conn.NamedExecContext(ctx,
111 > templateCreateQueueMetadataQuery,
112 > row,
113 > )
114 > }
115
116 func (mdb *db) UpdateQueueMetadata(
127 ctx context.Context,
128 filter sqlplugin.QueueMetadataFilter,
129 > ) (*sqlplugin.QueueMetadataRow, error) { queue.go
130 > var row sqlplugin.QueueMetadataRow
131 > err := mdb.conn.GetContext(ctx,
132 > &row,
133 > templateGetQueueMetadataQuery,
134 > filter.QueueType,
135 > )
136 > if err != nil {
137 > return nil, err queue.go
138 > }
139 > return &row, nil queue.go
140 }
141
go.temporal.io/server/common/persistence/sql/task_store.go 17 covered LOC · 3 ranges

Open complete file

29 enableFairness bool,
30 serializer serialization.Serializer,
31 > ) (persistence.TaskStore, error) { task_store.go
32 > store := SqlStore{
33 > DB: db,
34 > logger: logger,
35 > serializer: serializer,
36 > }
37 > userDataStore := userDataStore{SqlStore: store}
38 > taskQueueStore := taskQueueStore{
39 > SqlStore: store,
40 > version: sqlplugin.MatchingTaskVersion1,
41 > taskScanPartitions: uint32(taskScanPartitions),
42 > }
43 > if enableFairness {
44 > taskQueueStore.version = sqlplugin.MatchingTaskVersion2 task_store.go
45 > return newTaskManagerV2(db, userDataStore, taskQueueStore, logger, serializer)
46 > }
47 > return newTaskManagerV1(db, userDataStore, taskQueueStore, logger, serializer) task_store.go
48 }
go.temporal.io/server/common/persistence/visibility/quotas.go 17 covered LOC · 4 ranges

Open complete file

19 maxQPS dynamicconfig.IntPropertyFn,
20 operatorRPSRatio dynamicconfig.FloatPropertyFn,
21 > ) quotas.RequestRateLimiter { quotas.go
22 > rateLimiters := make(map[int]quotas.RequestRateLimiter)
23 > for priority := range PrioritiesOrdered {
24 > if priority == OperatorPriority {
25 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(quotas.NewDefaultOutgoingRateLimiter(operatorRateFn(maxQPS, operatorRPSRatio)))
26 > } else {
27 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(quotas.NewDefaultOutgoingRateLimiter(rateFn(maxQPS)))
28 > }
29 }
30 > return quotas.NewPriorityRateLimiter(func(req quotas.Request) int { quotas.go
31 if req.CallerType == headers.CallerTypeOperator {
32 return OperatorPriority
37 }
38
39 > func rateFn(maxQPS dynamicconfig.IntPropertyFn) quotas.RateFn { quotas.go
40 > return func() float64 {
41 > return float64(maxQPS())
42 > }
43 }
44
45 > func operatorRateFn(maxQPS dynamicconfig.IntPropertyFn, operatorRPSRatio dynamicconfig.FloatPropertyFn) quotas.RateFn { quotas.go
46 > return func() float64 {
47 > return float64(maxQPS()) * operatorRPSRatio()
48 > }
49 }
go.temporal.io/server/common/persistence/visibility/visiblity_manager_metrics.go 17 covered LOC · 3 ranges

Open complete file

35 visibilityPluginNameMetricsTag metrics.Tag,
36 visibilityIndexNameMetricsTag metrics.Tag,
37 > ) *visibilityManagerMetrics { visiblity_manager_metrics.go
38 > return &visibilityManagerMetrics{
39 > metricHandler: metricHandler,
40 > logger: logger,
41 > delegate: delegate,
42 >
43 > slowQueryThreshold: slowQueryThreshold,
44 > visibilityPluginNameMetricsTag: visibilityPluginNameMetricsTag,
45 > visibilityIndexNameMetricsTag: visibilityIndexNameMetricsTag,
46 > }
47 > }
48
49 > func (m *visibilityManagerMetrics) Close() { visiblity_manager_metrics.go
50 > m.delegate.Close()
51 > }
52
53 func (m *visibilityManagerMetrics) GetReadStoreName(nsName namespace.Name) string {
55 }
56
57 > func (m *visibilityManagerMetrics) GetStoreNames() []string { visiblity_manager_metrics.go
58 > return m.delegate.GetStoreNames()
59 > }
60
61 func (m *visibilityManagerMetrics) HasStoreName(stName string) bool {
go.temporal.io/server/common/rpc/interceptor/context_metadata_interceptor.go 17 covered LOC · 5 ranges

Open complete file

31
32 // NewContextMetadataInterceptor creates a new ContextMetadataInterceptor
33 > func NewContextMetadataInterceptor(setTrailer bool, logger log.Logger) *ContextMetadataInterceptor { context_metadata_interceptor.go
34 > cmi := &ContextMetadataInterceptor{
35 > setTrailer: setTrailer,
36 > }
37 > if setTrailer {
38 > cmi.logger = logger context_metadata_interceptor.go
39 > cmi.throttledLogger = log.NewThrottledLogger(logger, func() float64 {
40 > return 1.0 / 30.0 // 1 log per 30 seconds
41 > })
42 }
44 }
45
51 info *grpc.UnaryServerInfo,
52 handler grpc.UnaryHandler,
53 > ) (any, error) { context_metadata_interceptor.go
54 > ctx = contextutil.WithMetadataContext(ctx)
55 >
56 > resp, err := handler(ctx, req)
57 >
58 > if c.setTrailer {
59 c.appendContextMetadataToTrailer(ctx, info)
60 }
61
62 > return resp, err context_metadata_interceptor.go
63 }
64
go.temporal.io/server/common/rpc/interceptor/routing_key_extractor.go 17 covered LOC · 6 ranges

Open complete file

18 }
19
20 > func NewRoutingKeyExtractor() RoutingKeyExtractor { routing_key_extractor.go
21 > return RoutingKeyExtractor{
22 > serializer: *tasktoken.NewSerializer(),
23 > }
24 > }
25
26 // WorkflowServiceExtractor returns a RoutingKeyExtractorFunc that extracts the
27 // routing key from WorkflowService API requests using the provided
28 // RoutingKeyExtractor.
29 > func WorkflowServiceExtractor(extractor RoutingKeyExtractor) RoutingKeyExtractorFunc { routing_key_extractor.go
30 > return func(_ context.Context, req any, fullMethod string) namespace.RoutingKey {
31 > // Only process WorkflowService APIs
32 > if !strings.HasPrefix(fullMethod, api.WorkflowServicePrefix) {
33 return namespace.RoutingKey{}
34 }
36 // Prefer the generated extractor driven by temporal-resource-id proto
37 // annotations.
38 > if key := workflowServiceRequestRoutingKey(req); key.ID != "" { routing_key_extractor.go
39 > return key routing_key_extractor.go
40 > }
41
42 // Fall back to pattern-based logic as a compatibility path for methods
43 // whose callers haven't populated the resource_id field yet.
44 > methodName := api.MethodName(fullMethod) routing_key_extractor.go
45 > pattern, hasPattern := methodToPattern[methodName]
46 > if !hasPattern {
47 > return namespace.RoutingKey{} routing_key_extractor.go
48 > }
49
50 return extractor.Extract(req, pattern)
go.temporal.io/server/common/testing/testhooks/test_impl.go 17 covered LOC · 6 ranges

Open complete file

30 }
31
32 > func NewTestHooks() TestHooks { test_impl.go
33 > return TestHooks{data: &sync.Map{}}
34 > }
35
36 // Get gets the value of a test hook from the registry.
37 //
38 // TestHooks should be used sparingly, see comment on TestHooks.
39 > func Get[T any, S any](th TestHooks, key Key[T, S], scope S) (T, bool) { test_impl.go
40 > var zero T
41 > if th.data == nil {
42 // This means TestHooks wasn't created via NewTestHooks. Ignore.
43 return zero, false
44 }
45 > if val, ok := th.data.Load(hookKey{key.id, scope}); ok { test_impl.go
46 return val.(T), true //nolint:revive
47 }
48 > return zero, false test_impl.go
49 }
50
89 var keyCounter atomic.Int64
90
91 > func newKey[T any, S any]() Key[T, S] { test_impl.go
92 > var zero S
93 > var s ScopeType
94 > switch any(zero).(type) {
95 > case namespace.ID, namespace.Name:
96 > s = ScopeNamespace
97 > case global:
98 > s = ScopeGlobal
99 default:
100 panic("testhooks: unknown scope type")
101 }
102 > return Key[T, S]{id: keyCounter.Add(1), scopeType: s} test_impl.go
103 }
go.temporal.io/server/service/history/queues/scope.go 17 covered LOC · 6 ranges

Open complete file

18 r Range,
19 predicate tasks.Predicate,
20 > ) Scope { scope.go
21 > return Scope{
22 > Range: r,
23 > Predicate: predicate,
24 > }
25 > }
26
27 func (s *Scope) Contains(task tasks.Task) bool {
32 func (s *Scope) CanSplitByRange(
33 key tasks.Key,
34 > ) bool { scope.go
35 > return s.Range.CanSplit(key)
36 > }
37
38 func (s *Scope) SplitByRange(
39 key tasks.Key,
40 > ) (left Scope, right Scope) { scope.go
41 > if !s.CanSplitByRange(key) {
42 panic(fmt.Sprintf("Unable to split scope with range %v at %v", s.Range, key))
43 }
44
45 > leftRange, rightRange := s.Range.Split(key) scope.go
46 > return NewScope(leftRange, s.Predicate), NewScope(rightRange, s.Predicate)
47 }
48
94 }
95
96 > func (s *Scope) IsEmpty() bool { scope.go
97 > if s.Range.IsEmpty() {
98 > return true scope.go
99 > }
100
101 if _, ok := s.Predicate.(*predicates.EmptyImpl[tasks.Task]); ok {
go.temporal.io/server/service/history/replication/dlq_writer.go 17 covered LOC · 3 ranges

Open complete file

59
60 // NewExecutionManagerDLQWriter creates a new DLQWriter that uses the [ExecutionManager].
61 > func NewExecutionManagerDLQWriter(executionManager ExecutionManager) *executionManagerDLQWriter { dlq_writer.go
62 > return &executionManagerDLQWriter{
63 > executionManager: executionManager,
64 > }
65 > }
66
67 // NewDLQWriterAdapter creates a new DLQWriter from a QueueV2 [queues.DLQWriter].
70 replicationTaskSerializer TaskSerializer,
71 currentClusterName string,
72 > ) *DLQWriterAdapter { dlq_writer.go
73 > return &DLQWriterAdapter{
74 > dlqWriter: dlqWriter,
75 > replicationTaskSerializer: replicationTaskSerializer,
76 > currentClusterName: currentClusterName,
77 > }
78 > }
79
80 // This creates a new [DLQWriter] that can be toggled between the two implementations.
81 func newDLQWriterToggle(
82 params dlqWriterToggleParams,
83 > ) DLQWriter { dlq_writer.go
84 > return &dlqWriterToggle{
85 > dlqWriterToggleParams: &params,
86 > }
87 > }
88
89 // WriteTaskToDLQ implements [DLQWriter.WriteTaskToDLQ] by calling either
go.temporal.io/server/service/history/timer_queue_standby_task_executor.go 17 covered LOC · 1 range

Open complete file

54 config *configs.Config,
55 clientBean client.Bean,
56 > ) queues.Executor { timer_queue_standby_task_executor.go
57 > return &timerQueueStandbyTaskExecutor{
58 > timerQueueTaskExecutorBase: newTimerQueueTaskExecutorBase(
59 > shard,
60 > workflowCache,
61 > workflowDeleteManager,
62 > matchingRawClient,
63 > chasmEngine,
64 > logger,
65 > metricProvider,
66 > config,
67 > false,
68 > ),
69 > clusterName: clusterName,
70 > clientBean: clientBean,
71 > }
72 > }
73
74 func (t *timerQueueStandbyTaskExecutor) Execute(
go.temporal.io/server/service/history/timer_queue_task_executor_base.go 17 covered LOC · 1 range

Open complete file

61 config *configs.Config,
62 isActive bool,
63 > ) *timerQueueTaskExecutorBase { timer_queue_task_executor_base.go
64 > return &timerQueueTaskExecutorBase{
65 > stateMachineEnvironment: stateMachineEnvironment{
66 > shardContext: shardContext,
67 > cache: workflowCache,
68 > logger: logger,
69 > metricsHandler: metricsHandler,
70 > },
71 > currentClusterName: shardContext.GetClusterMetadata().GetCurrentClusterName(),
72 > registry: shardContext.GetNamespaceRegistry(),
73 > chasmEngine: chasmEngine,
74 > deleteManager: deleteManager,
75 > matchingRawClient: matchingRawClient,
76 > config: config,
77 > isActive: isActive,
78 > }
79 > }
80
81 func (t *timerQueueTaskExecutorBase) executeDeleteHistoryEventTask(
go.temporal.io/server/service/history/workflow/cache/cache.go 17 covered LOC · 4 ranges

Open complete file

95 logger log.Logger,
96 handler metrics.Handler,
97 > ) Cache { cache.go
98 > maxSize := config.HistoryHostLevelCacheMaxSize()
99 > if config.HistoryCacheLimitSizeBased {
100 maxSize = config.HistoryHostLevelCacheMaxSizeBytes()
101 }
102 > opts := &cache.Options{ cache.go
103 > TTL: config.HistoryCacheTTL(),
104 > Pin: true,
105 > BackgroundEvict: config.HistoryCacheBackgroundEvict,
106 > OnPut: func(val any) {
107 //revive:disable-next-line:unchecked-type-assertion
108 item := val.(*cacheItem)
141 }
142
143 > taggedHandler := handler.WithTags(metrics.CacheTypeTag(metrics.MutableStateCacheTypeTagValue)) cache.go
144 > c := cache.NewWithMetrics(maxSize, opts, taggedHandler)
145 > return &cacheImpl{
146 > Cache: c,
147 > nonUserContextLockTimeout: config.HistoryCacheNonUserContextLockTimeout(),
148 > }
149 }
150
151 > func (c *cacheImpl) stop() { cache.go
152 > c.Cache.(cache.StoppableCache).Stop()
153 > }
154
155 func (c *cacheImpl) GetOrCreateWorkflowExecution(
go.temporal.io/server/service/worker/deletenamespace/deleteexecutions/activities.go 17 covered LOC · 2 ranges

Open complete file

72 metricsHandler metrics.Handler,
73 logger log.Logger,
74 > ) *Activities { activities.go
75 > return &Activities{
76 > visibilityManager: visibilityManager,
77 > historyClient: historyClient,
78 > deleteActivityRPS: deleteActivityRPS,
79 > useChasmDeleteExecution: useChasmDeleteExecution,
80 > metricsHandler: metricsHandler,
81 > logger: logger,
82 > }
83 > }
84
85 func NewLocalActivities(
87 metricsHandler metrics.Handler,
88 logger log.Logger,
89 > ) *LocalActivities { activities.go
90 > return &LocalActivities{
91 > visibilityManager: visibilityManager,
92 > metricsHandler: metricsHandler,
93 > logger: logger,
94 > }
95 > }
96
97 func (a *LocalActivities) GetNextPageTokenActivity(ctx context.Context, params GetNextPageTokenParams) ([]byte, error) {
go.temporal.io/server/chasm/interceptors.go 16 covered LOC · 3 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) *ChasmEngineInterceptor { interceptors.go
40 > return &ChasmEngineInterceptor{
41 > engine: engine,
42 > logger: logger,
43 > metricsHandler: metricsHandler,
44 > }
45 > }
46
47 // ChasmVisibilityInterceptor intercepts RPC requests and adds the CHASM
56 info *grpc.UnaryServerInfo,
57 handler grpc.UnaryHandler,
58 > ) (resp any, retError error) { interceptors.go
59 > ctx = NewVisibilityManagerContext(ctx, i.visibilityMgr)
60 > return handler(ctx, req)
61 > }
62
63 > func ChasmVisibilityInterceptorProvider(visibilityMgr VisibilityManager) *ChasmVisibilityInterceptor { interceptors.go
64 > return &ChasmVisibilityInterceptor{
65 > visibilityMgr: visibilityMgr,
66 > }
67 > }
go.temporal.io/server/chasm/library_core.go 16 covered LOC · 3 ranges

Open complete file

6 }
7
8 > func (b *CoreLibrary) Name() string { library_core.go
9 > return "core"
10 > }
11
12 > func (b *CoreLibrary) Components() []*RegistrableComponent { library_core.go
13 > return []*RegistrableComponent{
14 > NewRegistrableComponent[*Visibility]("vis", WithDetached()),
15 > }
16 > }
17
18 > func (b *CoreLibrary) Tasks() []*RegistrableTask { library_core.go
19 > return []*RegistrableTask{
20 > NewRegistrableSideEffectTask(
21 > "visTask",
22 > defaultVisibilityTaskHandler,
23 > ),
24 > }
25 > }
go.temporal.io/server/common/nexus/nexusrpc/server.go 16 covered LOC · 6 ranges

Open complete file

380
381 // NewHTTPHandler constructs an [http.Handler] from given options for handling Nexus service requests.
382 > func NewHTTPHandler(options HandlerOptions) http.Handler { server.go
383 > if options.Logger == nil {
384 options.Logger = slog.Default()
385 }
386 > if options.GetResultTimeout == 0 { server.go
387 options.GetResultTimeout = time.Minute
388 }
389 > if options.Serializer == nil { server.go
390 options.Serializer = nexus.DefaultSerializer()
391 }
392 > if options.FailureConverter == nil { server.go
393 > options.FailureConverter = DefaultFailureConverter() server.go
394 > }
395 > handler := &httpHandler{ server.go
396 > BaseHTTPHandler: BaseHTTPHandler{
397 > Logger: options.Logger,
398 > FailureConverter: options.FailureConverter,
399 > },
400 > options: options,
401 > }
402 >
403 > return http.HandlerFunc(handler.handleRequest)
404 }
go.temporal.io/server/common/quotas/multi_reservation_impl.go 16 covered LOC · 6 ranges

Open complete file

17 ok bool,
18 reservations []Reservation,
19 > ) *MultiReservationImpl { multi_reservation_impl.go
20 > if ok && len(reservations) == 0 {
21 panic("expect at least one reservation")
22 }
23 > return &MultiReservationImpl{ multi_reservation_impl.go
24 > ok: ok,
25 > reservations: reservations,
26 > }
27 }
28
29 // OK returns whether the limiter can provide the requested number of tokens
30 > func (r *MultiReservationImpl) OK() bool { multi_reservation_impl.go
31 > return r.ok
32 > }
33
34 // Cancel indicates that the reservation holder will not perform the reserved action
59 // before taking the reserved action. Zero duration means act immediately.
60 // MultiReservation DelayFrom returns the maximum delay of all its sub-reservations.
61 > func (r *MultiReservationImpl) DelayFrom(now time.Time) time.Duration { multi_reservation_impl.go
62 > if !r.ok {
63 return InfDuration
64 }
65
66 > result := r.reservations[0].DelayFrom(now) multi_reservation_impl.go
67 > for _, reservation := range r.reservations {
68 > duration := reservation.DelayFrom(now)
69 > if result < duration {
70 result = duration
71 }
72 }
73 > return result multi_reservation_impl.go
74 }
go.temporal.io/server/common/rpc/encryption/local_store_cert_provider.go 16 covered LOC · 2 ranges

Open complete file

53 type tlsCertFetcher func() (*tls.Certificate, error)
54
55 > func (s *localStoreCertProvider) initialize() { local_store_cert_provider.go
56 >
57 > if s.refreshInterval != 0 {
58 s.stop = make(chan bool)
59 s.ticker = time.NewTicker(s.refreshInterval)
67 legacyWorkerSettings *config.ClientTLS,
68 refreshInterval time.Duration,
69 > logger log.Logger) CertProvider { local_store_cert_provider.go
70 >
71 > provider := &localStoreCertProvider{
72 > tlsSettings: tlsSettings,
73 > workerTLSSettings: workerTlsSettings,
74 > legacyWorkerSettings: legacyWorkerSettings,
75 > isLegacyWorkerConfig: legacyWorkerSettings != nil,
76 > logger: logger,
77 > refreshInterval: refreshInterval,
78 > }
79 > provider.initialize()
80 > return provider
81 > }
82
83 func (s *localStoreCertProvider) Close() {
go.temporal.io/server/common/rpc/interceptor/service_error_interceptor.go 16 covered LOC · 4 ranges

Open complete file

21 func NewServiceErrorInterceptor(
22 maxMessageLength dynamicconfig.IntPropertyFn,
23 > ) *ServiceErrorInterceptor { service_error_interceptor.go
24 > return &ServiceErrorInterceptor{
25 > maxMessageLength: maxMessageLength,
26 > }
27 > }
28
29 func (i *ServiceErrorInterceptor) Intercept(
32 _ *grpc.UnaryServerInfo,
33 handler grpc.UnaryHandler,
34 > ) (any, error) { service_error_interceptor.go
35 > resp, err := handler(ctx, req)
36 >
37 > var deserializationError *serialization.DeserializationError
38 > var serializationError *serialization.SerializationError
39 > // convert serialization errors to be captured as serviceerrors across gRPC calls
40 > if errors.As(err, &deserializationError) || errors.As(err, &serializationError) {
41 err = serviceerror.NewDataLoss(err.Error())
42 }
43
44 // truncate message length if needed
45 > maxLength := i.maxMessageLength() service_error_interceptor.go
46 > st := serviceerror.ToStatus(err)
47 > if len(st.Message()) > maxLength {
48 p := st.Proto()
49 p.Message = util.TruncateUTF8(p.Message, maxLength-len(truncatedSuffix)) + truncatedSuffix
go.temporal.io/server/common/rpc/interceptor/slow_request_logger.go 16 covered LOC · 3 ranges

Open complete file

23 logger log.Logger,
24 slowRequestThreshold dynamicconfig.DurationPropertyFn,
25 > ) *SlowRequestLoggerInterceptor { slow_request_logger.go
26 > return &SlowRequestLoggerInterceptor{
27 > logger: logger,
28 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
29 > slowRequestThreshold: slowRequestThreshold,
30 > }
31 > }
32
33 func (i *SlowRequestLoggerInterceptor) Intercept(
36 info *grpc.UnaryServerInfo,
37 handler grpc.UnaryHandler,
38 > ) (any, error) { slow_request_logger.go
39 > // Long-polled methods aren't useful logged.
40 > if api.GetMethodMetadata(info.FullMethod).Polling == api.PollingNone {
41 > startTime := time.Now()
42 >
43 > defer func() {
44 > elapsed := time.Since(startTime)
45 > if elapsed > i.slowRequestThreshold() {
46 i.logSlowRequest(request, info, elapsed)
47 }
go.temporal.io/server/common/searchattribute/manager.go 16 covered LOC · 1 range

Open complete file

53 logger log.Logger,
54 forceRefresh dynamicconfig.BoolPropertyFn,
55 > ) *managerImpl { manager.go
56 > var saCache atomic.Value
57 > saCache.Store(cache{
58 > searchAttributes: map[string]NameTypeMap{},
59 > dbVersion: 0,
60 > expireOn: time.Time{},
61 > })
62 >
63 > return &managerImpl{
64 > logger: logger,
65 > timeSource: timeSource,
66 > cache: saCache,
67 > clusterMetadataManager: clusterMetadataManager,
68 > forceRefresh: forceRefresh,
69 > }
70 > }
71
72 // GetSearchAttributes returns all search attributes (including system and build-in) for specified index.
go.temporal.io/server/service/frontend/nexus_endpoint_client.go 16 covered LOC · 2 ranges

Open complete file

53 )
54
55 > func newNexusEndpointClientConfig(dc *dynamicconfig.Collection) *nexusEndpointClientConfig { nexus_endpoint_client.go
56 > maxDescriptionSizeFn := dynamicconfig.NexusEndpointDescriptionMaxSize.Get(dc)
57 >
58 > return &nexusEndpointClientConfig{
59 > maxNameLength: dynamicconfig.NexusEndpointNameMaxLength.Get(dc),
60 > maxTaskQueueLength: dynamicconfig.MaxIDLengthLimit.Get(dc),
61 > maxDescriptionSize: func() int {
62 return maxDescriptionSizeFn("") // Ignore namespace for endpoints since they are global resources.
63 },
74 persistence p.NexusEndpointManager,
75 logger log.Logger,
76 > ) *NexusEndpointClient { nexus_endpoint_client.go
77 > return &NexusEndpointClient{
78 > config: config,
79 > namespaceRegistry: namespaceRegistry,
80 > matchingClient: matchingClient,
81 > persistence: persistence,
82 > logger: logger,
83 > }
84 > }
85
86 func (c *NexusEndpointClient) Create(
go.temporal.io/server/service/history/outbound_queue_standby_task_executor.go 16 covered LOC · 1 range

Open complete file

41 chasmEngine chasm.Engine,
42 clientBean client.Bean,
43 > ) *outboundQueueStandbyTaskExecutor { outbound_queue_standby_task_executor.go
44 > return &outboundQueueStandbyTaskExecutor{
45 > stateMachineEnvironment: stateMachineEnvironment{
46 > shardContext: shardCtx,
47 > cache: workflowCache,
48 > logger: logger,
49 > metricsHandler: metricsHandler.WithTags(
50 > metrics.OperationTag(metrics.OperationOutboundQueueProcessorScope),
51 > ),
52 > },
53 > config: shardCtx.GetConfig(),
54 > clusterName: clusterName,
55 > chasmEngine: chasmEngine,
56 > clientBean: clientBean,
57 > }
58 > }
59
60 func (e *outboundQueueStandbyTaskExecutor) Execute(
go.temporal.io/server/service/history/transfer_queue_standby_task_executor.go 16 covered LOC · 1 range

Open complete file

58 chasmEngine chasm.Engine,
59 clientBean client.Bean,
60 > ) queues.Executor { transfer_queue_standby_task_executor.go
61 > return &transferQueueStandbyTaskExecutor{
62 > transferQueueTaskExecutorBase: newTransferQueueTaskExecutorBase(
63 > shard,
64 > workflowCache,
65 > logger,
66 > metricProvider,
67 > historyRawClient,
68 > matchingRawClient,
69 > visibilityManager,
70 > chasmEngine,
71 > ),
72 > clusterName: clusterName,
73 > clientBean: clientBean,
74 > }
75 > }
76
77 func (t *transferQueueStandbyTaskExecutor) Execute(
go.temporal.io/server/common/goro/group.go 15 covered LOC · 4 ranges

Open complete file

27 // exit on their own (possibly never).
28 // NOTE: Errors returned by the supplied function are ignored.
29 > func (g *Group) Go(f func(ctx context.Context) error) { group.go
30 > g.initOnce.Do(g.init)
31 > g.wg.Go(func() {
32 > _ = f(g.ctx)
33 > })
34 }
35
36 // Cancel cancels the `context.Context` that was passed to all goroutines
37 // spawned via `Go` on this `Group`.
38 > func (g *Group) Cancel() { group.go
39 > g.initOnce.Do(g.init)
40 > g.cancel()
41 > }
42
43 // Wait blocks waiting for all goroutines spawned via `Go` on this `Group`
44 // instance to complete. If `Go` has not been called then this function returns
45 // immediately.
46 > func (g *Group) Wait() { group.go
47 > g.wg.Wait()
48 > }
49
50 > func (g *Group) init() { group.go
51 > g.ctx, g.cancel = context.WithCancel(context.Background())
52 > }
go.temporal.io/server/common/persistence/visibility/store/sql/query_converter_util_legacy.go 15 covered LOC · 3 ranges

Open complete file

68 }
69
70 > func newColName(name string) *colName { query_converter_util_legacy.go
71 > return &colName{Name: name}
72 > }
73
74 func newSAColName(
77 fieldName string,
78 valueType enumspb.IndexedValueType,
79 > ) *saColName { query_converter_util_legacy.go
80 > return &saColName{
81 > dbColName: newColName(dbColName),
82 > alias: alias,
83 > fieldName: fieldName,
84 > valueType: valueType,
85 > }
86 > }
87
88 func newFuncExpr(name string, exprs ...sqlparser.Expr) *sqlparser.FuncExpr {
105 }
106
107 > func getMaxDatetimeValue() time.Time { query_converter_util_legacy.go
108 > t, _ := time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
109 > return t
110 > }
111
112 // formatComparisonExprStringForError formats comparison expression after
go.temporal.io/server/common/rpc/interceptor/namespace.go 15 covered LOC · 7 ranges

Open complete file

25 namespaceRegistry namespace.Registry,
26 req any,
27 > ) namespace.Name { namespace.go
28 > namespaceName, err := GetNamespaceName(namespaceRegistry, req)
29 > if err != nil {
30 > return namespace.EmptyName namespace.go
31 > }
32 > return namespaceName namespace.go
33 }
34
36 namespaceRegistry namespace.Registry,
37 req any,
38 > ) (namespace.Name, error) { namespace.go
39 > switch request := req.(type) {
40 case *workflowservice.RegisterNamespaceRequest:
41 // For namespace registration requests, we don't expect to find namespace so skip checking caches
42 // to avoid caching a NotFound error from persistence readthrough
43 return namespace.Name(request.GetNamespace()), nil
44 > case NamespaceNameGetter: namespace.go
45 > namespaceName := namespace.Name(request.GetNamespace())
46 > _, err := namespaceRegistry.GetNamespace(namespaceName)
47 > if err != nil {
48 return namespace.EmptyName, err
49 }
50 > return namespaceName, nil namespace.go
51
52 case NamespaceIDGetter:
58 return namespaceName, nil
59
60 > default: namespace.go
61 > return namespace.EmptyName, serviceerror.NewInternalf("unable to extract namespace info from request of type %T", req)
62 }
63 }
go.temporal.io/server/common/rpc/interceptor/retry.go 15 covered LOC · 3 ranges

Open complete file

20 policy backoff.RetryPolicy,
21 isRetryable backoff.IsRetryable,
22 > ) *RetryableInterceptor { retry.go
23 > return &RetryableInterceptor{
24 > policy: policy,
25 > isRetryable: isRetryable,
26 > }
27 > }
28
29 func (i *RetryableInterceptor) Intercept(
32 info *grpc.UnaryServerInfo,
33 handler grpc.UnaryHandler,
34 > ) (any, error) { retry.go
35 > var response any
36 > op := func(ctx context.Context) error {
37 > var err error
38 > response, err = handler(ctx, req)
39 > return err
40 > }
41
42 > err := backoff.ThrottleRetryContext(ctx, op, i.policy, i.isRetryable) retry.go
43 > return response, err
44 }
go.temporal.io/server/common/searchattribute/validator.go 15 covered LOC · 1 range

Open complete file

59 metricsHandler metrics.Handler,
60 logger log.Logger,
61 > ) *Validator { validator.go
62 > return &Validator{
63 > searchAttributesProvider: searchAttributesProvider,
64 > searchAttributesMapperProvider: searchAttributesMapperProvider,
65 > searchAttributesNumberOfKeysLimit: searchAttributesNumberOfKeysLimit,
66 > searchAttributesSizeOfValueLimit: searchAttributesSizeOfValueLimit,
67 > searchAttributesTotalSizeLimit: searchAttributesTotalSizeLimit,
68 > visibilityManager: visibilityManager,
69 > allowList: allowList,
70 > suppressErrorSetSystemSearchAttribute: suppressErrorSetSystemSearchAttribute,
71 >
72 > metricsHandler: metricsHandler,
73 > logger: logger,
74 > }
75 > }
76
77 // Validate search attributes are valid for writing.
go.temporal.io/server/service/history/ndc/state_rebuilder.go 15 covered LOC · 1 range

Open complete file

85 shard historyi.ShardContext,
86 logger log.Logger,
87 > ) *StateRebuilderImpl { state_rebuilder.go
88 >
89 > return &StateRebuilderImpl{
90 > shard: shard,
91 > namespaceRegistry: shard.GetNamespaceRegistry(),
92 > eventsCache: shard.GetEventsCache(),
93 > clusterMetadata: shard.GetClusterMetadata(),
94 > executionMgr: shard.GetExecutionManager(),
95 > taskRefresher: workflow.NewTaskRefresher(shard),
96 > rebuiltHistorySize: 0,
97 > rebuiltExternalPayloadSize: 0,
98 > rebuiltExternalPayloadCount: 0,
99 > logger: logger,
100 > }
101 > }
102
103 func (r *StateRebuilderImpl) Rebuild(
go.temporal.io/server/service/history/tasks/fake_task.go 15 covered LOC · 3 ranges

Open complete file

23 category Category,
24 visibilityTimestamp time.Time,
25 > ) Task { fake_task.go
26 > return &FakeTask{
27 > WorkflowKey: workflowKey,
28 > TaskID: common.EmptyEventTaskID,
29 > Version: common.EmptyVersion,
30 > VisibilityTimestamp: visibilityTimestamp,
31 > Category: category,
32 > }
33 > }
34
35 func (f *FakeTask) GetKey() Key {
52 }
53
54 > func (f *FakeTask) SetTaskID(id int64) { fake_task.go
55 > f.TaskID = id
56 > }
57
58 > func (f *FakeTask) GetVisibilityTime() time.Time { fake_task.go
59 > return f.VisibilityTimestamp
60 > }
61
62 func (f *FakeTask) SetVisibilityTime(t time.Time) {
go.temporal.io/server/service/history/timer_queue_active_task_executor.go 15 covered LOC · 1 range

Open complete file

57 matchingRawClient resource.MatchingRawClient,
58 chasmEngine chasm.Engine,
59 > ) queues.Executor { timer_queue_active_task_executor.go
60 > return &timerQueueActiveTaskExecutor{
61 > timerQueueTaskExecutorBase: newTimerQueueTaskExecutorBase(
62 > shard,
63 > workflowCache,
64 > workflowDeleteManager,
65 > matchingRawClient,
66 > chasmEngine,
67 > logger,
68 > metricProvider,
69 > config,
70 > true,
71 > ),
72 > }
73 > }
74
75 func (t *timerQueueActiveTaskExecutor) Execute(
go.temporal.io/server/service/worker/deletenamespace/reclaimresources/activities.go 15 covered LOC · 2 ranges

Open complete file

36 visibilityManager manager.VisibilityManager,
37 logger log.Logger,
38 > ) *Activities { activities.go
39 > return &Activities{
40 > visibilityManager: visibilityManager,
41 > logger: logger,
42 > }
43 > }
44
45 func NewLocalActivities(
48 namespaceCacheRefreshInterval dynamicconfig.DurationPropertyFn,
49 logger log.Logger,
50 > ) *LocalActivities { activities.go
51 > return &LocalActivities{
52 > visibilityManager: visibilityManager,
53 > metadataManager: metadataManager,
54 > logger: logger,
55 >
56 > namespaceCacheRefreshInterval: namespaceCacheRefreshInterval,
57 > }
58 > }
59
60 func (a *LocalActivities) IsAdvancedVisibilityActivity(_ context.Context, _ namespace.Name) (bool, error) {
go.temporal.io/server/chasm/lib/callback/tasks.go 14 covered LOC · 2 ranges

Open complete file

93 }
94
95 > func newInvocationTaskHandler(opts invocationTaskHandlerOptions) *invocationTaskHandler { tasks.go
96 > return &invocationTaskHandler{
97 > config: opts.Config,
98 > namespaceRegistry: opts.NamespaceRegistry,
99 > metricsHandler: opts.MetricsHandler,
100 > logger: opts.Logger,
101 > httpCallerProvider: opts.HTTPCallerProvider,
102 > httpTraceProvider: opts.HTTPTraceProvider,
103 > historyClient: opts.HistoryClient,
104 > }
105 > }
106
107 func (h *invocationTaskHandler) Validate(ctx chasm.Context, cb *Callback, attrs chasm.TaskInvocation, task *callbackspb.InvocationTask) (bool, error) {
157 }
158
159 > func newBackoffTaskHandler(opts backoffTaskHandlerOptions) *backoffTaskHandler { tasks.go
160 > return &backoffTaskHandler{}
161 > }
162
163 // Execute toggles the callback status from BACKING_OFF to SCHEDULED to trigger a new invocation attempt.
go.temporal.io/server/chasm/lib/scheduler/scheduler_tasks.go 14 covered LOC · 2 ranges

Open complete file

41 }
42
43 > func NewSchedulerIdleTaskHandler(opts SchedulerIdleTaskHandlerOptions) *SchedulerIdleTaskHandler { scheduler_tasks.go
44 > return &SchedulerIdleTaskHandler{
45 > config: opts.Config,
46 > metricsHandler: opts.MetricsHandler,
47 > baseLogger: opts.BaseLogger,
48 > }
49 > }
50
51 func (r *SchedulerIdleTaskHandler) Execute(
134 }
135
136 > func NewSchedulerCallbacksTaskHandler(opts SchedulerCallbacksTaskHandlerOptions) *SchedulerCallbacksTaskHandler { scheduler_tasks.go
137 > return &SchedulerCallbacksTaskHandler{
138 > config: opts.Config,
139 > historyClient: opts.HistoryClient,
140 > frontendClient: opts.FrontendClient,
141 > }
142 > }
143
144 // watchResult holds the outcome of watchRunningStart for a single BufferedStart.
go.temporal.io/server/chasm/library.go 14 covered LOC · 5 ranges

Open complete file

34 }
35
36 > func (UnimplementedLibrary) Tasks() []*RegistrableTask { library.go
37 > return nil
38 > }
39
40 // RegisterServices Registers the gRPC calls to the handlers of the library.
41 > func (UnimplementedLibrary) RegisterServices(_ *grpc.Server) { library.go
42 > }
43
44 > func (UnimplementedLibrary) NexusServices() []*nexus.Service { library.go
45 > return nil
46 > }
47
48 > func (UnimplementedLibrary) NexusServiceProcessors() []*NexusServiceProcessor { library.go
49 > return nil
50 > }
51
52 func (UnimplementedLibrary) mustEmbedUnimplementedLibrary() {}
56 // tasks within the CHASM framework.
57 // The format of the returned FQN is: "libName.name"
58 > func FullyQualifiedName(libName, name string) string { library.go
59 > return libName + "." + name
60 > }
go.temporal.io/server/common/build/build.go 14 covered LOC · 2 ranges

Open complete file

27 )
28
29 > func init() { build.go
30 > buildInfo, ok := debug.ReadBuildInfo()
31 > if !ok {
32 return
33 }
34
35 > InfoData.Available = true build.go
36 > InfoData.GoVersion = buildInfo.GoVersion
37 >
38 > for _, setting := range buildInfo.Settings {
39 > switch setting.Key {
40 > case "GOARCH":
41 > InfoData.GoArch = setting.Value
42 > case "GOOS":
43 > InfoData.GoOs = setting.Value
44 > case "CGO_ENABLED":
45 > InfoData.CgoEnabled = setting.Value == "1"
46 case "vcs.revision":
47 InfoData.GitRevision = setting.Value
go.temporal.io/server/common/config/fx.go 14 covered LOC · 4 ranges

Open complete file

15 )
16
17 > func provideRPCConfig(cfg *Config, svcName primitives.ServiceName) *RPC { fx.go
18 > c := cfg.Services[string(svcName)].RPC
19 >
20 > return &c
21 > }
22
23 > func provideMembershipConfig(cfg *Config) *Membership { fx.go
24 > return &cfg.Global.Membership
25 > }
26
27 > func provideServicePortMap(cfg *Config) ServicePortMap { fx.go
28 > servicePortMap := make(ServicePortMap)
29 > for sn, sc := range cfg.Services {
30 > servicePortMap[primitives.ServiceName(sn)] = sc.RPC.GRPCPort
31 > }
32
33 > return servicePortMap fx.go
34 }
go.temporal.io/server/common/persistence/visibility/visibility_manager_impl.go 14 covered LOC · 3 ranges

Open complete file

54 searchAttributesMapperProvider searchattribute.MapperProvider,
55 chasmRegistry *chasm.Registry,
56 > ) *visibilityManagerImpl { visibility_manager_impl.go
57 > return &visibilityManagerImpl{
58 > store: store,
59 > logger: logger,
60 > searchAttributesMapperProvider: searchAttributesMapperProvider,
61 > chasmRegistry: chasmRegistry,
62 > }
63 > }
64
65 > func (p *visibilityManagerImpl) Close() { visibility_manager_impl.go
66 > p.store.Close()
67 > }
68
69 func (p *visibilityManagerImpl) GetReadStoreName(_ namespace.Name) string {
71 }
72
73 > func (p *visibilityManagerImpl) GetStoreNames() []string { visibility_manager_impl.go
74 > return []string{p.store.GetName()}
75 > }
76
77 func (p *visibilityManagerImpl) HasStoreName(stName string) bool {
go.temporal.io/server/common/util/error_type.go 14 covered LOC · 4 ranges

Open complete file

27 // Otherwise, the type name of the first non-wrapper error in the depth-first traversal of err's tree is returned.
28 // We consider errors wrapped via [fmt.Errorf], [errors.Join] and some pkg/errors functions to be wrapper errors.
29 > func ErrorType(err error) string { error_type.go
30 > // If any error in the tree has an explicit type name, use it, preferring the first one in the DFS traversal.
31 > var typedErr typedError
32 > if errors.As(err, &typedErr) {
33 return typedErr.ErrorTypeName()
34 }
35
36 // Special case for context.Cancel error. It is of type errorString, which is not very useful.
37 > if errors.Is(err, context.Canceled) { error_type.go
38 return "context.Canceled"
39 }
40 // Special case for context.DeadlineExceeded error. It is of unexported type deadlineExceededError.
41 > if errors.Is(err, context.DeadlineExceeded) { error_type.go
42 return "context.DeadlineExceeded"
43 }
44
45 // Otherwise, do a DFS traversal of the error tree, ignoring wrapper errors.
46 > q := []error{err} error_type.go
47 > for len(q) > 0 {
48 > err = q[len(q)-1]
49 > q = q[:len(q)-1]
50 > errType := fmt.Sprintf("%T", err)
51 > if !wrapperErrorTypes[errType] {
52 > return strings.TrimPrefix(errType, "*")
53 > }
54 // The error could implement zero or one of the unary or multi-error wrapper interfaces. It's impossible to
55 // implement both because they have the same method name. As a result, this is still deterministic.
go.temporal.io/server/service/frontend/namespace_handler.go 14 covered LOC · 1 range

Open complete file

77 timeSource clock.TimeSource,
78 config *Config,
79 > ) *namespaceHandler { namespace_handler.go
80 > return &namespaceHandler{
81 > logger: logger,
82 > metadataMgr: metadataMgr,
83 > namespaceRegistry: namespaceRegistry,
84 > clusterMetadata: clusterMetadata,
85 > namespaceReplicator: namespaceReplicator,
86 > namespaceAttrValidator: nsmanager.NewValidator(clusterMetadata),
87 > archivalMetadata: archivalMetadata,
88 > archiverProvider: archiverProvider,
89 > timeSource: timeSource,
90 > config: config,
91 > }
92 > }
93
94 // RegisterNamespace register a new namespace
go.temporal.io/server/service/history/queues/iterator.go 14 covered LOC · 3 ranges

Open complete file

33 paginationFnProvider PaginationFnProvider,
34 r Range,
35 > ) *IteratorImpl { iterator.go
36 > return &IteratorImpl{
37 > paginationFnProvider: paginationFnProvider,
38 > remainingRange: r,
39 >
40 > // lazy initialized to prevent task pre-fetching on creating the iterator
41 > pagingIterator: nil,
42 > }
43 > }
44
45 > func (i *IteratorImpl) HasNext() bool { iterator.go
46 > if i.pagingIterator == nil {
47 > i.pagingIterator = collection.NewPagingIterator(i.paginationFnProvider(i.remainingRange))
48 > }
49
50 > return i.pagingIterator.HasNext() iterator.go
51 }
52
go.temporal.io/server/service/history/visibility_queue_task_executor.go 14 covered LOC · 1 range

Open complete file

56 relocateAttributesMinBlobSize dynamicconfig.IntPropertyFnWithNamespaceFilter,
57 externalPayloadsEnabled dynamicconfig.BoolPropertyFnWithNamespaceFilter,
58 > ) queues.Executor { visibility_queue_task_executor.go
59 > return &visibilityQueueTaskExecutor{
60 > shardContext: shardContext,
61 > cache: workflowCache,
62 > logger: logger,
63 > metricProvider: metricProvider,
64 > visibilityMgr: visibilityMgr,
65 >
66 > ensureCloseBeforeDelete: ensureCloseBeforeDelete,
67 > enableCloseWorkflowCleanup: enableCloseWorkflowCleanup,
68 > relocateAttributesMinBlobSize: relocateAttributesMinBlobSize,
69 > externalPayloadsEnabled: externalPayloadsEnabled,
70 > }
71 > }
72
73 func (t *visibilityQueueTaskExecutor) Execute(
go.temporal.io/server/service/worker/dummy/fx.go 14 covered LOC · 3 ranges

Open complete file

18 var Module = fx.Options(fx.Provide(NewResult))
19
20 > func NewResult() fxResult { fx.go
21 > return fxResult{
22 > Component: &workerComponent{},
23 > }
24 > }
25
26 > func (c *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, _ workercommon.RegistrationDetails) func() { fx.go
27 > registry.RegisterWorkflowWithOptions(DummyWorkflow, workflow.RegisterOptions{Name: DummyWFTypeName})
28 > return nil
29 > }
30
31 > func (c *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
32 > return &workercommon.PerNSDedicatedWorkerOptions{
33 > Enabled: true,
34 > }
35 > }
go.temporal.io/server/temporal/environment/env.go 14 covered LOC · 5 ranges

Open complete file

39 )
40
41 > func lookupLocalhostIP(domain string) string { env.go
42 > // lookup localhost and favor the first ipv4 address
43 > // unless there are only ipv6 addresses available
44 > ips, err := net.LookupIP(domain)
45 > if err != nil || len(ips) == 0 {
46 // fallback to default instead of error
47 return localhostIPDefault
48 }
49 > for _, ip := range ips { env.go
50 > if ip4 := ip.To4(); ip4 != nil {
51 > return ip4.String() env.go
52 > }
53 }
54 return ips[len(ips)-1].String()
56
57 // GetLocalhostIP returns the ip address of the localhost domain
58 > func GetLocalhostIP() string { env.go
59 > localhostIP := os.Getenv(localhostIPEnv)
60 > ip := net.ParseIP(localhostIP)
61 > if ip != nil {
62 // if localhost is an ip return it
63 return ip.String()
64 }
65 // otherwise, ignore the value and lookup `localhost`
66 > return lookupLocalhostIP("localhost") env.go
67 }
68
go.temporal.io/server/chasm/lib/activity/frontend.go 13 covered LOC · 1 range

Open complete file

65 saMapperProvider searchattribute.MapperProvider,
66 saValidator *searchattribute.Validator,
67 > ) FrontendHandler { frontend.go
68 > return &frontendHandler{
69 > callbackValidator: callbackValidator,
70 > linkValidator: linkValidator,
71 > client: client,
72 > config: config,
73 > logger: logger,
74 > metricsHandler: metricsHandler,
75 > namespaceRegistry: namespaceRegistry,
76 > saMapperProvider: saMapperProvider,
77 > saValidator: saValidator,
78 > }
79 > }
80
81 // IsStandaloneActivityEnabled checks if standalone activities are enabled for the given namespace
go.temporal.io/server/chasm/lib/nexusoperation/task_handler_base.go 13 covered LOC · 1 range

Open complete file

53 }
54
55 > func (o InvocationTaskHandlerOptions) toBase() nexusTaskHandlerBase { task_handler_base.go
56 > return nexusTaskHandlerBase{
57 > config: o.Config,
58 > namespaceRegistry: o.NamespaceRegistry,
59 > metricsHandler: o.MetricsHandler,
60 > logger: o.Logger,
61 > clientProvider: o.ClientProvider,
62 > endpointRegistry: o.EndpointRegistry,
63 > httpTraceProvider: o.HTTPTraceProvider,
64 > historyClient: o.HistoryClient,
65 > chasmRegistry: o.ChasmRegistry,
66 > }
67 > }
68
69 // nexusTaskHandlerBase contains common dependencies shared by the invocation and cancellation task handlers.
go.temporal.io/server/common/archiver/provider/provider.go 13 covered LOC · 1 range

Open complete file

107 logger log.Logger,
108 metricsHandler metrics.Handler,
109 > ) ArchiverProvider { provider.go
110 > return &archiverProvider{
111 > historyArchiverConfigs: historyArchiverConfigs,
112 > visibilityArchiverConfigs: visibilityArchiverConfigs,
113 > executionManager: executionManager,
114 > logger: logger,
115 > metricsHandler: metricsHandler,
116 > customHistoryArchiverFactory: customHistoryArchiverFactory,
117 > customVisibilityArchiverFactory: customVisibilityArchiverFactory,
118 > historyArchivers: make(map[string]archiver.HistoryArchiver),
119 > visibilityArchivers: make(map[string]archiver.VisibilityArchiver),
120 > }
121 > }
122
123 func (p *archiverProvider) GetHistoryArchiver(scheme string) (historyArchiver archiver.HistoryArchiver, err error) {
go.temporal.io/server/common/clock/time_source.go 13 covered LOC · 4 ranges

Open complete file

31
32 // NewRealTimeSource returns a timeSource that uses the real wall timeSource time.
33 > func NewRealTimeSource() RealTimeSource { time_source.go
34 > return RealTimeSource{}
35 > }
36
37 // Now returns the current time, with the location set to UTC.
38 > func (ts RealTimeSource) Now() time.Time { time_source.go
39 > return time.Now().UTC()
40 > }
41
42 // Since returns the time elapsed since t
46
47 // AfterFunc is a pass-through to time.AfterFunc.
48 > func (ts RealTimeSource) AfterFunc(d time.Duration, f func()) Timer { time_source.go
49 > return time.AfterFunc(d, f)
50 > }
51
52 // NewTimer is a pass-through to time.NewTimer.
53 > func (ts RealTimeSource) NewTimer(d time.Duration) (<-chan time.Time, Timer) { time_source.go
54 > t := time.NewTimer(d)
55 > return t.C, t
56 > }
go.temporal.io/server/common/cluster/frontend_http_client.go 13 covered LOC · 2 ranges

Open complete file

26 metadata Metadata,
27 tlsProvider tlsConfigProvider,
28 > ) *FrontendHTTPClientCache { frontend_http_client.go
29 > cache := &FrontendHTTPClientCache{
30 > metadata: metadata,
31 > tlsProvider: tlsProvider,
32 > }
33 > cache.clients = collection.NewFallibleOnceMap(cache.newClientForCluster)
34 > metadata.RegisterMetadataChangeCallback(cache, cache.evictionCallback)
35 > return cache
36 > }
37
38 // Get returns a cached HttpClient if available, or constructs a new one for the given cluster name.
92 // It invalidates clients which are either no longer present or have had their HTTP address changed.
93 // It is assumed that TLS information has not changed for clusters that are unmodified.
94 > func (c *FrontendHTTPClientCache) evictionCallback(oldClusterMetadata map[string]*ClusterInformation, newClusterMetadata map[string]*ClusterInformation) { frontend_http_client.go
95 > for oldClusterName, oldClusterInfo := range oldClusterMetadata {
96 > if oldClusterName == c.metadata.GetCurrentClusterName() || oldClusterInfo == nil {
97 > continue
98 }
99
go.temporal.io/server/common/membership/ringpop/fx.go 13 covered LOC · 4 ranges

Open complete file

13 )
14
15 > func provideFactory(lc fx.Lifecycle, params factoryParams) (*factory, error) { fx.go
16 > f, err := newFactory(params)
17 > if err != nil {
18 return nil, err
19 }
20 > lc.Append(fx.StopHook(f.closeTChannel)) fx.go
21 > return f, nil
22 }
23
24 > func provideMembership(lc fx.Lifecycle, f *factory) membership.Monitor { fx.go
25 > m := f.getMonitor()
26 > lc.Append(fx.StopHook(m.Stop))
27 > return m
28 > }
29
30 > func provideHostInfoProvider(lc fx.Lifecycle, f *factory) (membership.HostInfoProvider, error) { fx.go
31 > return f.getHostInfoProvider()
32 > }
go.temporal.io/server/common/metrics/defs_base.go 13 covered LOC · 2 ranges

Open complete file

10 }
11
12 > func newMetricDefinition(name string, opts ...Option) metricDefinition { defs_base.go
13 > d := metricDefinition{
14 > name: name,
15 > description: "",
16 > unit: "",
17 > }
18 > for _, opt := range opts {
19 > opt.apply(&d)
20 > }
21 > return d
22 }
23
24 > func (md metricDefinition) Name() string { defs_base.go
25 > return md.name
26 > }
27
28 func (md metricDefinition) Unit() MetricUnit {
go.temporal.io/server/common/namespace/mutate.go 13 covered LOC · 3 ranges

Open complete file

8 type mutationFunc func(*Namespace)
9
10 > func (f mutationFunc) apply(ns *Namespace) { mutate.go
11 > f(ns)
12 > }
13
14 // WithActiveCluster assigns the active cluster to a Namespace during a Clone
43
44 // WithGlobalFlag sets whether or not this Namespace is global.
45 > func WithGlobalFlag(b bool) Mutation { mutate.go
46 > return mutationFunc(
47 > func(ns *Namespace) {
48 > ns.replicationResolver.SetGlobalFlag(b)
49 > })
50 }
51
52 // WithNotificationVersion assigns a notification version to the Namespace.
53 > func WithNotificationVersion(v int64) Mutation { mutate.go
54 > return mutationFunc(
55 > func(ns *Namespace) {
56 > ns.notificationVersion = v
57 > })
58 }
59
go.temporal.io/server/common/nexus/nexusrpc/completion.go 13 covered LOC · 5 ranges

Open complete file

308
309 // NewCompletionHTTPHandler constructs an [http.Handler] from given options for handling operation completion requests.
310 > func NewCompletionHTTPHandler(options CompletionHandlerOptions) http.Handler { completion.go
311 > if options.Logger == nil {
312 options.Logger = slog.Default()
313 }
314 > if options.Serializer == nil { completion.go
315 options.Serializer = nexus.DefaultSerializer()
316 }
317 > if options.FailureConverter == nil { completion.go
318 > options.FailureConverter = DefaultFailureConverter() completion.go
319 > }
320 > return &completionHTTPHandler{ completion.go
321 > options: options,
322 > BaseHTTPHandler: BaseHTTPHandler{
323 > Logger: options.Logger,
324 > FailureConverter: options.FailureConverter,
325 > },
326 > }
327 }
go.temporal.io/server/common/persistence/visibility/visibility_manager_rate_limited.go 13 covered LOC · 3 ranges

Open complete file

31 writeMaxQPS dynamicconfig.IntPropertyFn,
32 operatorRPSRatio dynamicconfig.FloatPropertyFn,
33 > ) *visibilityManagerRateLimited { visibility_manager_rate_limited.go
34 > return &visibilityManagerRateLimited{
35 > delegate: delegate,
36 > readRateLimiter: newPriorityRateLimiter(readMaxQPS, operatorRPSRatio),
37 > writeRateLimiter: newPriorityRateLimiter(writeMaxQPS, operatorRPSRatio),
38 > }
39 > }
40
41 > func (m *visibilityManagerRateLimited) Close() { visibility_manager_rate_limited.go
42 > m.delegate.Close()
43 > }
44
45 func (m *visibilityManagerRateLimited) GetReadStoreName(nsName namespace.Name) string {
47 }
48
49 > func (m *visibilityManagerRateLimited) GetStoreNames() []string { visibility_manager_rate_limited.go
50 > return m.delegate.GetStoreNames()
51 > }
52
53 func (m *visibilityManagerRateLimited) HasStoreName(stName string) bool {
go.temporal.io/server/common/rpc/dial_tracer.go 13 covered LOC · 1 range

Open complete file

22 mh metrics.Handler,
23 logger log.Logger,
24 > ) *dialTracer { dial_tracer.go
25 > l := log.With(
26 > logger,
27 > tag.String("service", "client"),
28 > tag.String("address", address),
29 > )
30 >
31 > return &dialTracer{
32 > address: address,
33 > metricsHandler: mh,
34 > logger: l,
35 > }
36 > }
37
38 func (d *dialTracer) beginNetworkDial(ctx context.Context) (context.Context, *networkDialTrace) {
go.temporal.io/server/common/rpc/interceptor/frontend_service_error.go 13 covered LOC · 4 ranges

Open complete file

26 func NewFrontendServiceErrorInterceptor(
27 logger log.Logger,
28 > ) grpc.UnaryServerInterceptor { frontend_service_error.go
29 > return func(
30 > ctx context.Context,
31 > req any,
32 > info *grpc.UnaryServerInfo,
33 > handler grpc.UnaryHandler,
34 > ) (any, error) {
35 > resp, err := handler(ctx, req)
36 > if err == nil {
37 > return resp, nil frontend_service_error.go
38 > }
39
40 > switch serviceErr := err.(type) { frontend_service_error.go
41 case *serviceerrors.ShardOwnershipLost:
42 err = serviceerror.NewUnavailable("shard unavailable, please backoff and retry")
go.temporal.io/server/common/rpc/interceptor/namespace_rate_limit.go 13 covered LOC · 3 ranges

Open complete file

58 pollWaitForToken dynamicconfig.BoolPropertyFnWithNamespaceFilter,
59 metricsHandler metrics.Handler,
60 > ) NamespaceRateLimitInterceptor { namespace_rate_limit.go
61 > return &NamespaceRateLimitInterceptorImpl{
62 > namespaceRegistry: namespaceRegistry,
63 > rateLimiter: rateLimiter,
64 > tokens: tokens,
65 > pollMethods: pollMethods,
66 > pollWaitForToken: pollWaitForToken,
67 > metricsHandler: metricsHandler,
68 > }
69 > }
70
71 func (ni *NamespaceRateLimitInterceptorImpl) Intercept(
74 info *grpc.UnaryServerInfo,
75 handler grpc.UnaryHandler,
76 > ) (any, error) { namespace_rate_limit.go
77 > if ns := MustGetNamespaceName(ni.namespaceRegistry, req); ns != namespace.EmptyName {
78 method := info.FullMethod
79 if IsLongPollGetWorkflowExecutionHistoryRequest(req) {
go.temporal.io/server/common/telemetry/env.go 13 covered LOC · 5 ranges

Open complete file

29 func SpanExportersFromEnv(
30 envVars envVarLookup,
31 > ) (map[SpanExporterType]otelsdktrace.SpanExporter, error) { env.go
32 > exporters := map[SpanExporterType]otelsdktrace.SpanExporter{}
33 >
34 > exporterTypes, ok := envVars(OtelTracesExporterTypesEnvKey)
35 > if !ok {
36 > return exporters, nil env.go
37 > }
38
39 for exporterType := range strings.SplitSeq(exporterTypes, ",") {
64 rsn primitives.ServiceName,
65 envVars envVarLookup,
66 > ) string { env.go
67 > // map "internal-frontend" to "frontend" for the purpose of tracing
68 > if rsn == primitives.InternalFrontendService {
69 rsn = primitives.FrontendService
70 }
71
72 // allow custom prefix via env vars
73 > serviceNamePrefix := "io.temporal" env.go
74 > if customServicePrefix, found := envVars(OtelServiceNameEnvKey); found {
75 serviceNamePrefix = customServicePrefix
76 }
77
78 > return fmt.Sprintf("%s.%s", serviceNamePrefix, string(rsn)) env.go
79 }
go.temporal.io/server/service/frontend/version_checker.go 13 covered LOC · 3 ranges

Open complete file

36 clusterMetadataManager persistence.ClusterMetadataManager,
37 sdkVersionRecorder *interceptor.SDKVersionInterceptor,
38 > ) *VersionChecker { version_checker.go
39 > return &VersionChecker{
40 > config: config,
41 > shutdownChan: make(chan struct{}),
42 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.VersionCheckScope)),
43 > clusterMetadataManager: clusterMetadataManager,
44 > sdkVersionRecorder: sdkVersionRecorder,
45 > }
46 > }
47
48 > func (vc *VersionChecker) Start() { version_checker.go
49 > if vc.config.EnableServerVersionCheck() {
50 vc.startOnce.Do(func() {
51 // TODO: specify a timeout for the context
60 }
61
62 > func (vc *VersionChecker) Stop() { version_checker.go
63 > if vc.config.EnableServerVersionCheck() {
64 vc.stopOnce.Do(func() {
65 close(vc.shutdownChan)
go.temporal.io/server/service/history/replication/eventhandler/resend_handler.go 13 covered LOC · 1 range

Open complete file

63 logger log.Logger,
64 config *configs.Config,
65 > ) ResendHandler { resend_handler.go
66 > return &resendHandlerImpl{
67 > namespaceRegistry: namespaceRegistry,
68 > clientBean: clientBean,
69 > serializer: serializer,
70 > engineProvider: historyEngineProvider,
71 > remoteHistoryFetcher: remoteHistoryFetcher,
72 > eventImporter: importer,
73 > logger: logger,
74 > clusterMetadata: clusterMetadata,
75 > config: config,
76 > }
77 > }
78
79 // ResendHistoryEvents is used to retrieve history events from remote and apply to current(passive) cluster. Mostly handle 3 cases:
go.temporal.io/server/service/history/shard/handover_tracker.go 13 covered LOC · 3 ranges

Open complete file

63
64 // NewDefaultHandoverTrackerFactory returns a factory that creates the default OSS HandoverTracker.
65 > func NewDefaultHandoverTrackerFactory() HandoverTrackerFactory { handover_tracker.go
66 > return func(params HandoverTrackerParams) HandoverTracker {
67 > return &defaultHandoverTracker{ handover_tracker.go
68 > handoverNamespaces: make(map[namespace.Name]*namespaceHandOverInfo),
69 > clusterMetadata: params.ClusterMetadata,
70 > getMaxReplicationTaskID: params.GetMaxReplicationTaskID,
71 > errorByStateFn: params.ErrorByStateFn,
72 > notifyReplicationFn: params.NotifyReplicationFn,
73 > logger: params.Logger,
74 > }
75 > }
76 }
77
128 }
129
130 > func (t *defaultHandoverTracker) ResolvePendingTaskIDs(maxReplicationTaskID int64) { handover_tracker.go
131 > for _, handoverInfo := range t.handoverNamespaces {
132 if handoverInfo.MaxReplicationTaskID == PendingMaxReplicationTaskID {
133 handoverInfo.MaxReplicationTaskID = maxReplicationTaskID
go.temporal.io/server/chasm/lib/nexusoperation/cancellation_tasks.go 12 covered LOC · 2 ranges

Open complete file

80 }
81
82 > func newCancellationInvocationTaskHandler(opts cancellationInvocationTaskHandlerOptions) *cancellationInvocationTaskHandler { cancellation_tasks.go
83 > return &cancellationInvocationTaskHandler{
84 > nexusTaskHandlerBase: opts.toBase(),
85 > }
86 > }
87
88 func (h *cancellationInvocationTaskHandler) Validate(
205 }
206
207 > func newCancellationBackoffTaskHandler(opts commonTaskHandlerOptions) *cancellationBackoffTaskHandler { cancellation_tasks.go
208 > return &cancellationBackoffTaskHandler{
209 > config: opts.Config,
210 > metricsHandler: opts.MetricsHandler,
211 > logger: opts.Logger,
212 > }
213 > }
214
215 func (h *cancellationBackoffTaskHandler) Validate(
go.temporal.io/server/chasm/lib/scheduler/config.go 12 covered LOC · 4 ranges

Open complete file

48
49 // contextValues builds the CHASM context values exposed to scheduler components.
50 > func (c *Config) contextValues() map[any]any { config.go
51 > var tweakables dynamicconfig.TypedPropertyFnWithNamespaceFilter[Tweakables]
52 > if c != nil {
53 > tweakables = c.Tweakables config.go
54 > }
55 > return map[any]any{tweakablesCtxKey: tweakables} config.go
56 }
57
98 )
99
100 > func ConfigProvider(dc *dynamicconfig.Collection) *Config { config.go
101 > return &Config{
102 > Tweakables: CurrentTweakables.Get(dc),
103 > ServiceCallTimeout: ServiceCallTimeout.Get(dc),
104 > EncodeInternalTokenWithEnvelope: callback.EncodeInternalTokenWithEnvelope.Get(dc),
105 > RetryPolicy: func() backoff.RetryPolicy {
106 return backoff.NewExponentialRetryPolicy(
107 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/client/history/metric_client.go 12 covered LOC · 2 ranges

Open complete file

29 logger log.Logger,
30 throttledLogger log.Logger,
31 > ) historyservice.HistoryServiceClient { metric_client.go
32 > return &metricClient{
33 > client: client,
34 > metricsHandler: metricsHandler,
35 > logger: logger,
36 > throttledLogger: throttledLogger,
37 > }
38 > }
39
40 > func (c *metricClient) Stop() { metric_client.go
41 > if s, ok := c.client.(interface{ Stop() }); ok {
42 > s.Stop()
43 > }
44 }
45
go.temporal.io/server/common/authorization/default_authorizer.go 12 covered LOC · 3 ranges

Open complete file

16
17 // NewDefaultAuthorizer creates a default authorizer
18 > func NewDefaultAuthorizer() Authorizer { default_authorizer.go
19 > return &defaultAuthorizer{}
20 > }
21
22 var resultAllow = Result{Decision: DecisionAllow}
33 // Namespace Writer is allowed to access non admin APIs on their namespaces.
34 // Namespace Reader is allowed to access non admin readonly APIs on their namespaces.
35 > func (a *defaultAuthorizer) Authorize(_ context.Context, claims *Claims, target *CallTarget) (Result, error) { default_authorizer.go
36 > // APIs that are essentially read-only health checks with no sensitive information are
37 > // always allowed
38 > if IsHealthCheckAPI(target.APIName) {
39 > return resultAllow, nil
40 > }
41 > if claims == nil {
42 > return resultDeny, nil default_authorizer.go
43 > }
44
45 metadata := api.GetMethodMetadata(target.APIName)
go.temporal.io/server/common/backoff/jitter.go 12 covered LOC · 4 ranges

Open complete file

4
5 // FullJitter return random number from 0 to input, inclusive, exclusive
6 > func FullJitter[T ~int64 | ~int | ~int32 | ~float64 | ~float32](input T) T { jitter.go
7 > return T(rand.Float64() * float64(input))
8 > }
9
10 // Jitter return random number from (1-coefficient)*input to (1+coefficient)*input, inclusive, exclusive
11 > func Jitter[T ~int64 | ~int | ~int32 | ~float64 | ~float32](input T, coefficient float64) T { jitter.go
12 > validateCoefficient(coefficient)
13 >
14 > if coefficient == 0 {
15 return input
16 }
17
18 > base := float64(input) * (1 - coefficient) jitter.go
19 > addon := rand.Float64() * 2 * (float64(input) - base)
20 > return T(base + addon)
21 }
22
23 > func validateCoefficient(coefficient float64) { jitter.go
24 > if coefficient < 0 || coefficient > 1 {
25 panic("coefficient cannot be < 0 or > 1")
26 }
go.temporal.io/server/common/cluster/fx.go 12 covered LOC · 3 ranges

Open complete file

12 fx.Invoke(MetadataLifetimeHooks),
13 fx.Provide(fx.Annotate(
14 > func(p Metadata) pingable.Pingable { return p }, fx.go
15 fx.ResultTags(`group:"deadlockDetectorRoots"`),
16 )),
20 lc fx.Lifecycle,
21 clusterMetadata Metadata,
22 > ) { fx.go
23 > lc.Append(
24 > fx.Hook{
25 > OnStart: func(context.Context) error {
26 > clusterMetadata.Start()
27 > return nil
28 > },
29 > OnStop: func(context.Context) error { fx.go
30 > clusterMetadata.Stop()
31 > return nil
32 > },
33 },
34 )
go.temporal.io/server/common/collection/oncemap.go 12 covered LOC · 2 ranges

Open complete file

13 // NewOnceMap creates a [OnceMap] from a given construct function.
14 // construct should be kept light as it is called while holding a lock on the entire map.
15 > func NewOnceMap[K comparable, T any](construct func(K) T) *OnceMap[K, T] { oncemap.go
16 > return &OnceMap[K, T]{
17 > construct: construct,
18 > inner: make(map[K]T, 0),
19 > }
20 > }
21
22 func (m *OnceMap[K, T]) Get(key K) T {
47 // NewFallibleOnceMap creates a [FallibleOnceMap] from a given construct function.
48 // construct should be kept light as it is called while holding a lock on the entire map.
49 > func NewFallibleOnceMap[K comparable, T any](construct func(K) (T, error)) *FallibleOnceMap[K, T] { oncemap.go
50 > return &FallibleOnceMap[K, T]{
51 > construct: construct,
52 > inner: make(map[K]T, 0),
53 > }
54 > }
55
56 func (p *FallibleOnceMap[K, T]) Get(key K) (T, error) {
go.temporal.io/server/common/config/archival.go 12 covered LOC · 4 ranges

Open complete file

15
16 // Validate validates the archival config
17 > func (a *Archival) Validate(namespaceDefaults *ArchivalNamespaceDefaults) error { archival.go
18 > if !isArchivalConfigValid(a.History.State, a.History.EnableRead, namespaceDefaults.History.State, namespaceDefaults.History.URI, a.History.Provider != nil) {
19 return errors.New("invalid history archival config")
20 }
21
22 > if !isArchivalConfigValid(a.Visibility.State, a.Visibility.EnableRead, namespaceDefaults.Visibility.State, namespaceDefaults.Visibility.URI, a.Visibility.Provider != nil) { archival.go
23 return errors.New("invalid visibility archival config")
24 }
25
26 > return nil archival.go
27 }
28
33 domianDefaultURI string,
34 specifiedProvider bool,
35 > ) bool { archival.go
36 > archivalEnabled := clusterStatus == ArchivalEnabled
37 > URISet := len(domianDefaultURI) != 0
38 >
39 > validEnable := archivalEnabled && URISet && specifiedProvider
40 > validDisabled := !archivalEnabled && !enableRead && namespaceDefaultStatus != ArchivalEnabled && !URISet && !specifiedProvider
41 > return validEnable || validDisabled
42 > }
go.temporal.io/server/common/convert/convert.go 12 covered LOC · 4 ranges

Open complete file

16 }
17
18 > func IntToString(v int) string { convert.go
19 > return Int64ToString(int64(v))
20 > }
21
22 func Uint64ToString(v uint64) string {
24 }
25
26 > func Int64ToString(v int64) string { convert.go
27 > return strconv.FormatInt(v, 10)
28 > }
29
30 > func Int32ToString(v int32) string { convert.go
31 > return Int64ToString(int64(v))
32 > }
33
34 > func Uint16ToString(v uint16) string { convert.go
35 > return strconv.FormatUint(uint64(v), 10)
36 > }
37
38 func Int64SetToSlice(
go.temporal.io/server/common/dynamicconfig/registry.go 12 covered LOC · 4 ranges

Open complete file

17 )
18
19 > func register(s GenericSetting) { registry.go
20 > if globalRegistry.queried.Load() {
21 panic("dynamicconfig.New*Setting must only be called from static initializers")
22 }
23 > if globalRegistry.settings == nil { registry.go
24 > globalRegistry.settings = make(map[Key]GenericSetting)
25 > }
26 > if globalRegistry.settings[s.Key()] != nil {
27 // nolint:forbidigo // only called during static initialization
28 panic(fmt.Sprintf("duplicate registration of dynamic config key: %q", s.Key().String()))
29 }
30 > globalRegistry.settings[s.Key()] = s registry.go
31 }
32
33 > func queryRegistry(k Key) GenericSetting { registry.go
34 > if !globalRegistry.queried.Load() {
35 > globalRegistry.queried.Store(true)
36 > }
37 > return globalRegistry.settings[k]
38 }
39
go.temporal.io/server/common/persistence/visibility/store/elasticsearch/visibility_store.go 12 covered LOC · 3 ranges

Open complete file

101 }
102
103 > defaultSorter = func() []elastic.Sorter { visibility_store.go
104 > ret := make([]elastic.Sorter, 0, len(defaultSorterFields))
105 > for _, item := range defaultSorterFields {
106 > fs := elastic.NewFieldSort(item.name)
107 > if item.desc {
108 > fs.Desc()
109 > }
110 > if item.missing_first {
111 > fs.Missing("_first")
112 > } else {
113 fs.Missing("_last")
114 }
115 > ret = append(ret, fs) visibility_store.go
116 }
117 > return ret visibility_store.go
118 }()
119
go.temporal.io/server/common/persistence/xdc_cache.go 12 covered LOC · 1 range

Open complete file

90 ttl time.Duration,
91 logger log.Logger,
92 > ) *XDCCacheImpl { xdc_cache.go
93 > return &XDCCacheImpl{
94 > cache: cache.New(
95 > max(xdcMinCacheSize, maxBytes),
96 > &cache.Options{
97 > TTL: ttl,
98 > Pin: false,
99 > },
100 > ),
101 > logger: logger,
102 > }
103 > }
104
105 func (e *XDCCacheImpl) Put(
go.temporal.io/server/common/primitives/timestamp/duration.go 12 covered LOC · 4 ranges

Open complete file

26 }
27
28 > func DurationPtr(td time.Duration) *durationpb.Duration { duration.go
29 > return durationpb.New(td)
30 > }
31
32 func MinDurationPtr(d1 *durationpb.Duration, d2 *durationpb.Duration) *durationpb.Duration {
43 }
44
45 > func DurationFromHours(h int64) *durationpb.Duration { duration.go
46 > return durationMultipleOf(h, time.Hour)
47 > }
48
49 > func DurationFromDays(d int32) *durationpb.Duration { duration.go
50 > return durationMultipleOf(int64(d), time.Hour*24)
51 > }
52
53 > func durationMultipleOf(amt int64, mult time.Duration) *durationpb.Duration { duration.go
54 > return DurationPtr(time.Duration(amt) * mult)
55 > }
56
57 // ValidateAndCapProtoDuration validates protobuf durations for two conditions:
go.temporal.io/server/common/quotas/priority_reservation_impl.go 12 covered LOC · 3 ranges

Open complete file

17 decidingReservation Reservation,
18 otherReservations []Reservation,
19 > ) *PriorityReservationImpl { priority_reservation_impl.go
20 > return &PriorityReservationImpl{
21 > decidingReservation: decidingReservation,
22 > otherReservations: otherReservations,
23 > }
24 > }
25
26 // OK returns whether the limiter can provide the requested number of tokens
27 > func (r *PriorityReservationImpl) OK() bool { priority_reservation_impl.go
28 > return r.decidingReservation.OK()
29 > }
30
31 // Cancel indicates that the reservation holder will not perform the reserved action
52 // DelayFrom returns the duration for which the reservation holder must wait
53 // before taking the reserved action. Zero duration means act immediately.
54 > func (r *PriorityReservationImpl) DelayFrom(now time.Time) time.Duration { priority_reservation_impl.go
55 > return r.decidingReservation.DelayFrom(now)
56 > }
go.temporal.io/server/common/rpc/interceptor/health.go 12 covered LOC · 4 ranges

Open complete file

23
24 // NewHealthInterceptor returns a new HealthInterceptor. It starts with state not healthy.
25 > func NewHealthInterceptor() *HealthInterceptor { health.go
26 > return &HealthInterceptor{}
27 > }
28
29 func (i *HealthInterceptor) Intercept(
32 info *grpc.UnaryServerInfo,
33 handler grpc.UnaryHandler,
34 > ) (any, error) { health.go
35 > // only enforce health check on WorkflowService and OperatorService
36 > if strings.HasPrefix(info.FullMethod, api.WorkflowServicePrefix) ||
37 > strings.HasPrefix(info.FullMethod, api.OperatorServicePrefix) {
38 > if !i.healthy.Load() {
39 return nil, notHealthyErr
40 }
41 }
42 > return handler(ctx, req) health.go
43 }
44
45 > func (i *HealthInterceptor) SetHealthy(healthy bool) { health.go
46 > i.healthy.Store(healthy)
47 > }
go.temporal.io/server/common/rpc/interceptor/trailer_to_context_metadata_interceptor.go 12 covered LOC · 1 range

Open complete file

19 // Requires the context to be pre-wrapped with contextutil.WithMetadataContext() before the RPC call.
20 // This is typically done by server-side interceptors (e.g., ContextMetadataInterceptor).
21 > func TrailerToContextMetadataInterceptor(logger log.Logger) grpc.UnaryClientInterceptor { trailer_to_context_metadata_interceptor.go
22 > throttledLogger := log.NewThrottledLogger(logger, func() float64 {
23 > return 1.0 / 30.0 // 1 log per 30 seconds
24 > })
25 > return func(
26 > ctx context.Context,
27 > method string,
28 > req, reply any,
29 > cc *grpc.ClientConn,
30 > invoker grpc.UnaryInvoker,
31 > opts ...grpc.CallOption,
32 > ) error {
33 var trailer metadata.MD
34 opts = append(opts, grpc.Trailer(&trailer))
go.temporal.io/server/common/telemetry/grpc.go 12 covered LOC · 5 ranges

Open complete file

44 tmp propagation.TextMapPropagator,
45 logger log.Logger,
46 > ) ServerStatsHandler { grpc.go
47 > if !isEnabled(tp) {
48 > return nil grpc.go
49 > }
50
51 return newCustomServerStatsHandler(
64 tp trace.TracerProvider,
65 tmp propagation.TextMapPropagator,
66 > ) ClientStatsHandler { grpc.go
67 > if !isEnabled(tp) {
68 > return nil grpc.go
69 > }
70
71 return otelgrpc.NewClientHandler(
192 }
193
194 > func isEnabled(tp trace.TracerProvider) bool { grpc.go
195 > _, isNoop := tp.(otelnoop.TracerProvider)
196 > return !isNoop
197 > }
go.temporal.io/server/service/history/deletemanager/delete_manager.go 12 covered LOC · 1 range

Open complete file

64 timeSource clock.TimeSource,
65 visibilityManager manager.VisibilityManager,
66 > ) *DeleteManagerImpl { delete_manager.go
67 > deleteManager := &DeleteManagerImpl{
68 > shardContext: shardContext,
69 > workflowCache: cache,
70 > metricsHandler: shardContext.GetMetricsHandler(),
71 > config: config,
72 > timeSource: timeSource,
73 > visibilityManager: visibilityManager,
74 > }
75 >
76 > return deleteManager
77 > }
78
79 func (m *DeleteManagerImpl) AddDeleteExecutionTask(
go.temporal.io/server/service/history/ndc/workflow_resetter.go 12 covered LOC · 1 range

Open complete file

88 workflowCache wcache.Cache,
89 logger log.Logger,
90 > ) *workflowResetterImpl { workflow_resetter.go
91 > return &workflowResetterImpl{
92 > shardContext: shardContext,
93 > namespaceRegistry: shardContext.GetNamespaceRegistry(),
94 > clusterMetadata: shardContext.GetClusterMetadata(),
95 > executionMgr: shardContext.GetExecutionManager(),
96 > workflowCache: workflowCache,
97 > stateRebuilder: NewStateRebuilder(shardContext, logger),
98 > transaction: workflow.NewTransaction(shardContext),
99 > logger: logger,
100 > }
101 > }
102
103 // ResetWorkflow resets the given base run and creates a new run that would start after baseNextEventID. It additionally does the following
go.temporal.io/server/service/history/queues/mitigator.go 12 covered LOC · 1 range

Open complete file

43 maxReaderCount dynamicconfig.IntPropertyFn,
44 grouper Grouper,
45 > ) *mitigatorImpl { mitigator.go
46 > return &mitigatorImpl{
47 > readerGroup: readerGroup,
48 > monitor: monitor,
49 > logger: logger,
50 > metricsHandler: metricsHandler,
51 > maxReaderCount: maxReaderCount,
52 >
53 > actionRunner: runAction,
54 > grouper: grouper,
55 > }
56 > }
57
58 func (m *mitigatorImpl) Mitigate(alert Alert) {
go.temporal.io/server/service/history/queues/priority_assigner.go 12 covered LOC · 3 ranges

Open complete file

23 )
24
25 > func NewPriorityAssigner(nsRegistry namespace.Registry, currentClusterName string) PriorityAssigner { priority_assigner.go
26 > return &priorityAssignerImpl{
27 > nsRegistry: nsRegistry,
28 > currentClusterName: currentClusterName,
29 > }
30 > }
31
32 func (a *priorityAssignerImpl) Assign(executable Executable) tasks.Priority {
65 }
66
67 > func NewNoopPriorityAssigner() PriorityAssigner { priority_assigner.go
68 > return NewStaticPriorityAssigner(tasks.PriorityHigh)
69 > }
70
71 > func NewStaticPriorityAssigner(priority tasks.Priority) PriorityAssigner { priority_assigner.go
72 > return staticPriorityAssigner{priority: priority}
73 > }
74
75 func (a staticPriorityAssigner) Assign(_ Executable) tasks.Priority {
go.temporal.io/server/chasm/lib/callback/fx.go 11 covered LOC · 4 ranges

Open complete file

19 registry *chasm.Registry,
20 library *Library,
21 > ) error { fx.go
22 > return registry.Register(library)
23 > }
24
25 // httpCallerProviderProvider provides an HTTPCallerProvider for CHASM callbacks.
30 httpClientCache *cluster.FrontendHTTPClientCache,
31 logger log.Logger,
32 > ) (HTTPCallerProvider, error) { fx.go
33 > localClient, err := rpcFactory.CreateLocalFrontendHTTPClient()
34 > if err != nil {
35 return nil, fmt.Errorf("cannot create local frontend HTTP client: %w", err)
36 }
37 > defaultClient := &http.Client{} fx.go
38 > callbackTokenGenerator := commonnexus.NewCallbackTokenGenerator()
39 >
40 > m := collection.NewOnceMap(func(queuescommon.NamespaceIDAndDestination) HTTPCaller {
41 return func(r *http.Request) (*http.Response, error) {
42 return routeRequest(r,
51 }
52 })
53 > return m.Get, nil fx.go
54 }
55
go.temporal.io/server/chasm/lib/nexusoperation/frontend.go 11 covered LOC · 1 range

Open complete file

52 saMapperProvider searchattribute.MapperProvider,
53 saValidator *searchattribute.Validator,
54 > ) FrontendHandler { frontend.go
55 > return &frontendHandler{
56 > client: client,
57 > config: config,
58 > logger: logger,
59 > namespaceRegistry: namespaceRegistry,
60 > endpointRegistry: endpointRegistry,
61 > saMapperProvider: saMapperProvider,
62 > saValidator: saValidator,
63 > }
64 > }
65
66 func (h *frontendHandler) StartNexusOperationExecution(
go.temporal.io/server/common/log/noop_logger.go 11 covered LOC · 7 ranges

Open complete file

10
11 // NewNoopLogger return a noopLogger
12 > func NewNoopLogger() *noopLogger { noop_logger.go
13 > return &noopLogger{}
14 > }
15
16 > func (n *noopLogger) Debug(string, ...tag.Tag) {} noop_logger.go
17 > func (n *noopLogger) Info(string, ...tag.Tag) {} noop_logger.go
18 > func (n *noopLogger) Warn(string, ...tag.Tag) {} noop_logger.go
19 > func (n *noopLogger) Error(string, ...tag.Tag) {} noop_logger.go
20 func (n *noopLogger) DPanic(string, ...tag.Tag) {}
21 func (n *noopLogger) Panic(string, ...tag.Tag) {}
22 > func (n *noopLogger) Fatal(string, ...tag.Tag) {} noop_logger.go
23 > func (n *noopLogger) With(...tag.Tag) Logger { noop_logger.go
24 > return n
25 > }
go.temporal.io/server/common/log/slog.go 11 covered LOC · 6 ranges

Open complete file

27
28 // NewSlogLogger creates an slog.Logger from a given logger.
29 > func NewSlogLogger(logger Logger) *slog.Logger { slog.go
30 > // Try extracting and underlying slog logger (e.g. for Temporal CLI).
31 > if sl, ok := logger.(SLogWrapper); ok {
32 return sl.SLog()
33 }
34 > logger = withIncreasedSkip(logger, 3) slog.go
35 > return slog.New(&handler{logger: logger, zapLogger: extractZapLogger(logger), group: "", tags: nil})
36 }
37
94 }
95
96 > func extractZapLogger(logger Logger) *zap.Logger { slog.go
97 > switch l := logger.(type) {
98 case *zapLogger:
99 return l.zl
103 return extractZapLogger(l.logger)
104 }
105 > return nil slog.go
106 }
107
108 // withIncreasedSkip increases the skip level for the given logger if it embeds a zapLogger.
109 > func withIncreasedSkip(logger Logger, skip int) Logger { slog.go
110 > switch l := logger.(type) {
111 case *zapLogger:
112 return l.Skip(skip)
123 }
124 // Default to not increasing the skip, it's better to have a logger than not having one.
125 > return logger slog.go
126 }
127
go.temporal.io/server/common/metrics/fx.go 11 covered LOC · 2 ranges

Open complete file

17 lc fx.Lifecycle,
18 reporter *RuntimeMetricsReporter,
19 > ) { fx.go
20 > lc.Append(
21 > fx.Hook{
22 > OnStart: func(context.Context) error {
23 > reporter.Start()
24 > return nil
25 > },
26 > OnStop: func(context.Context) error { fx.go
27 > reporter.Stop()
28 > return nil
29 > },
30 },
31 )
go.temporal.io/server/common/quotas/request_rate_limiter_adapter_impl.go 11 covered LOC · 3 ranges

Open complete file

16 func NewRequestRateLimiterAdapter(
17 rateLimiter RateLimiter,
18 > ) RequestRateLimiter { request_rate_limiter_adapter_impl.go
19 > return &RequestRateLimiterAdapterImpl{
20 > rateLimiter: rateLimiter,
21 > }
22 > }
23
24 func (r *RequestRateLimiterAdapterImpl) Allow(
25 now time.Time,
26 request Request,
28 > return r.rateLimiter.AllowN(now, request.Token)
29 > }
30
31 func (r *RequestRateLimiterAdapterImpl) Reserve(
32 now time.Time,
33 request Request,
35 > return r.rateLimiter.ReserveN(now, request.Token)
36 > }
37
38 func (r *RequestRateLimiterAdapterImpl) Wait(
go.temporal.io/server/common/rpc/interceptor/namespace_logger.go 11 covered LOC · 3 ranges

Open complete file

23 var _ grpc.UnaryServerInterceptor = (*NamespaceLogInterceptor)(nil).Intercept
24
25 > func NewNamespaceLogInterceptor(namespaceRegistry namespace.Registry, logger log.Logger) *NamespaceLogInterceptor { namespace_logger.go
26 >
27 > return &NamespaceLogInterceptor{
28 > namespaceRegistry: namespaceRegistry,
29 > logger: logger,
30 > }
31 > }
32
33 func (nli *NamespaceLogInterceptor) Intercept(
36 info *grpc.UnaryServerInfo,
37 handler grpc.UnaryHandler,
38 > ) (any, error) { namespace_logger.go
39 >
40 > if nli.logger != nil {
41 methodName := api.MethodName(info.FullMethod)
42 namespace := MustGetNamespaceName(nli.namespaceRegistry, req)
58 tag.CertThumbprint(certThumbprint))
59 }
60 > return handler(ctx, req) namespace_logger.go
61 }
go.temporal.io/server/common/telemetry/config.go 11 covered LOC · 4 ranges

Open complete file

157 }
158
159 > func (ec *ExportConfig) SpanExporters() (map[SpanExporterType]otelsdktrace.SpanExporter, error) { config.go
160 > return ec.inner.SpanExporters()
161 > }
162
163 func (ec *ExportConfig) MetricExporters() ([]metric.Exporter, error) {
205 // unmarshalled into this ExportConfig object. The returned SpanExporters have
206 // not been started.
207 > func (ec *exportConfig) SpanExporters() (map[SpanExporterType]otelsdktrace.SpanExporter, error) { config.go
208 > out := make(map[SpanExporterType]otelsdktrace.SpanExporter, len(ec.Exporters))
209 > for _, expcfg := range ec.Exporters {
210 if !strings.HasPrefix(expcfg.Kind.Signal, "trace") {
211 continue
222 }
223 }
224 > return out, nil config.go
225 }
226
417 }
418
419 > func IsEnabled(t trace.Tracer) bool { config.go
420 > _, isNoop := t.(otelnoop.Tracer)
421 > return !isNoop
422 > }
go.temporal.io/server/service/history/configs/quotas.go 11 covered LOC · 2 ranges

Open complete file

22 rateFn quotas.RateFn,
23 operatorRPSRatio dynamicconfig.FloatPropertyFn,
24 > ) quotas.RequestRateLimiter { quotas.go
25 > return quotas.NewPriorityRateLimiterHelper(
26 > quotas.NewDefaultIncomingRateBurst(rateFn),
27 > operatorRPSRatio,
28 > RequestToPriority,
29 > APIPrioritiesOrdered,
30 > )
31 > }
32
33 func NewNamespaceRateLimiter(
34 namespaceRateFn quotas.NamespaceRateFn,
35 operatorRPSRatio dynamicconfig.FloatPropertyFn,
36 > ) quotas.RequestRateLimiter { quotas.go
37 > return quotas.NewNamespaceRequestRateLimiter(
38 > func(req quotas.Request) quotas.RequestRateLimiter {
39 return quotas.NewPriorityRateLimiterHelper(
40 quotas.NewNamespaceRateBurst(
go.temporal.io/server/service/history/replication/eager_namespace_refresher.go 11 covered LOC · 1 range

Open complete file

43 replicationTaskExecutor nsreplication.TaskExecutor,
44 currentCluster string,
45 > metricsHandler metrics.Handler) EagerNamespaceRefresher { eager_namespace_refresher.go
46 > return &eagerNamespaceRefresherImpl{
47 > metadataManager: metadataManager,
48 > namespaceRegistry: namespaceRegistry,
49 > logger: logger,
50 > clientBean: clientBean,
51 > replicationTaskExecutor: replicationTaskExecutor,
52 > currentCluster: currentCluster,
53 > metricsHandler: metricsHandler,
54 > }
55 > }
56
57 func (e *eagerNamespaceRefresherImpl) SyncNamespaceFromSourceCluster(
go.temporal.io/server/service/history/replication/quotas.go 11 covered LOC · 3 ranges

Open complete file

15 )
16
17 > func ClientSchedulerRateLimiterProvider() ClientSchedulerRateLimiter { quotas.go
18 > // Experiment with no op rate limiter
19 > return quotas.NoopRequestRateLimiter
20 > }
21
22 > func ServerSchedulerRateLimiterProvider() ServerSchedulerRateLimiter { quotas.go
23 > // Experiment with no op rate limiter
24 > return quotas.NoopRequestRateLimiter
25 > }
26
27 > func PersistenceRateLimiterProvider() PersistenceRateLimiter { quotas.go
28 > return quotas.NoopRequestRateLimiter
29 > }
go.temporal.io/server/service/matching/configs/quotas.go 11 covered LOC · 2 ranges

Open complete file

65 rateFn quotas.RateFn,
66 operatorRPSRatio dynamicconfig.FloatPropertyFn,
67 > ) quotas.RequestRateLimiter { quotas.go
68 > return quotas.NewPriorityRateLimiterHelper(
69 > quotas.NewDefaultIncomingRateBurst(rateFn),
70 > operatorRPSRatio,
71 > RequestToPriority,
72 > APIPrioritiesOrdered,
73 > )
74 > }
75
76 func NewNamespaceRateLimiter(
77 namespaceRateFn quotas.NamespaceRateFn,
78 operatorRPSRatio dynamicconfig.FloatPropertyFn,
79 > ) quotas.RequestRateLimiter { quotas.go
80 > return quotas.NewNamespaceRequestRateLimiter(
81 > func(req quotas.Request) quotas.RequestRateLimiter {
82 return quotas.NewPriorityRateLimiterHelper(
83 quotas.NewNamespaceRateBurst(
go.temporal.io/server/service/worker/deletenamespace/activities.go 11 covered LOC · 1 range

Open complete file

49 allowDeleteNamespaceIfNexusEndpointTarget dynamicconfig.BoolPropertyFn,
50 nexusEndpointListDefaultPageSize dynamicconfig.IntPropertyFn,
51 > ) *localActivities { activities.go
52 > return &localActivities{
53 > metadataManager: metadataManager,
54 > clusterMetadata: clusterMetadata,
55 > nexusEndpointManager: nexusEndpointManager,
56 > logger: logger,
57 > protectedNamespaces: protectedNamespaces,
58 > allowDeleteNamespaceIfNexusEndpointTarget: allowDeleteNamespaceIfNexusEndpointTarget,
59 > nexusEndpointListDefaultPageSize: nexusEndpointListDefaultPageSize,
60 > }
61 > }
62
63 func (a *localActivities) GetNamespaceInfoActivity(ctx context.Context, nsID namespace.ID, nsName namespace.Name) (getNamespaceInfoResult, error) {
go.temporal.io/server/service/worker/scheduler/spec.go 11 covered LOC · 1 range

Open complete file

63 // NewSpecBuilder takes the compute-limit getters directly (rather than a *dynamicconfig.Collection)
64 // so the dynamic-config plumbing stays in the wiring layer, per the common codebase pattern.
65 > func NewSpecBuilder(warnIterations, maxIterations dynamicconfig.IntPropertyFn) *SpecBuilder { spec.go
66 > return &SpecBuilder{
67 > warnIterations: warnIterations,
68 > maxIterations: maxIterations,
69 > locationCache: cache.New(1000,
70 > &cache.Options{
71 > TTL: 24 * time.Hour,
72 > },
73 > ),
74 > }
75 > }
76
77 func (b *SpecBuilder) NewCompiledSpec(spec *schedulepb.ScheduleSpec) (*CompiledSpec, error) {
go.temporal.io/server/chasm/lib/activity/handler.go 10 covered LOC · 1 range

Open complete file

48 logger log.Logger,
49 namespaceRegistry namespace.Registry,
50 > ) *handler { handler.go
51 > return &handler{
52 > config: config,
53 > historyHandler: historyHandler,
54 > linkValidator: linkValidator,
55 > logger: logger,
56 > metricsHandler: metricsHandler,
57 > namespaceRegistry: namespaceRegistry,
58 > }
59 > }
60
61 // StartActivityExecution schedules an activity execution. Note that while external callers refer to
go.temporal.io/server/chasm/lib/scheduler/fx.go 10 covered LOC · 3 ranges

Open complete file

11 registry *chasm.Registry,
12 library *Library,
13 > ) error { fx.go
14 > return registry.Register(library)
15 > }
16
17 var Module = fx.Module(
18 "chasm.lib.scheduler",
19 fx.Provide(ConfigProvider),
20 > fx.Provide(func(dc *dynamicconfig.Collection) *legacyscheduler.SpecBuilder { fx.go
21 > return legacyscheduler.NewSpecBuilder(
22 > dynamicconfig.SchedulerSpecWarnIterations.Get(dc),
23 > dynamicconfig.SchedulerSpecMaxIterations.Get(dc),
24 > )
25 > }),
26 fx.Provide(NewSpecProcessor),
27 > fx.Provide(func(impl *SpecProcessorImpl) SpecProcessor { return impl }), fx.go
28 fx.Provide(newHandler),
29 fx.Provide(NewSchedulerIdleTaskHandler),
go.temporal.io/server/chasm/lib/tests/nexus_service.go 10 covered LOC · 2 ranges

Open complete file

12 })
13
14 > func NewTestServiceNexusService() *nexus.Service { nexus_service.go
15 > service := nexus.NewService("TestService")
16 > service.MustRegister(TestOperation)
17 > return service
18 > }
19
20 type testOperationProcessor struct {
30 }
31
32 > func NewTestServiceNexusServiceProcessor() *chasm.NexusServiceProcessor { nexus_service.go
33 > sp := chasm.NewNexusServiceProcessor("TestService")
34 > sp.MustRegisterOperation("TestOperation", chasm.NewRegisterableNexusOperationProcessor(testOperationProcessor{}))
35 > return sp
36 > }
go.temporal.io/server/client/matching/loadbalancer.go 10 covered LOC · 1 range

Open complete file

65 dc *dynamicconfig.Collection,
66 testHooks testhooks.TestHooks,
67 > ) LoadBalancer { loadbalancer.go
68 > lb := &defaultLoadBalancer{
69 > namespaceIDToName: namespaceIDToName,
70 > nReadPartitions: dynamicconfig.MatchingNumTaskqueueReadPartitions.Get(dc),
71 > nWritePartitions: dynamicconfig.MatchingNumTaskqueueWritePartitions.Get(dc),
72 > testHooks: testHooks,
73 > taskQueueLBs: make(map[tqid.TaskQueue]*tqLoadBalancer),
74 > }
75 > return lb
76 > }
77
78 func (lb *defaultLoadBalancer) PickWritePartition(
go.temporal.io/server/common/namespace/nsreplication/replication_task_executor.go 10 covered LOC · 1 range

Open complete file

68 logger log.Logger,
69 testHooks testhooks.TestHooks,
70 > ) TaskExecutor { replication_task_executor.go
71 > return &taskExecutorImpl{
72 > currentCluster: currentCluster,
73 > metadataManager: metadataManagerV2,
74 > dataMerger: dataMerger,
75 > admitter: admitter,
76 > logger: logger,
77 > testHooks: testHooks,
78 > }
79 > }
80
81 // Execute handles receiving of the namespace replication task
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/plugin.go 10 covered LOC · 1 range

Open complete file

36 var _ sqlplugin.Plugin = (*plugin)(nil)
37
38 > func init() { plugin.go
39 > sql.RegisterPlugin(PluginName, &plugin{
40 > driver: &driver.PQDriver{},
41 > queryConverter: &queryConverter{},
42 > })
43 > sql.RegisterPlugin(PluginNamePGX, &plugin{
44 > driver: &driver.PGXDriver{},
45 > queryConverter: &queryConverter{},
46 > })
47 > }
48
49 func (p *plugin) GetVisibilityQueryConverter() sqlplugin.VisibilityQueryConverter {
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/visibility.go 10 covered LOC · 1 range

Open complete file

40 )
41
42 > func buildOnDuplicateKeyUpdate(fields ...string) string { visibility.go
43 > items := make([]string, len(fields))
44 > for i, field := range fields {
45 > items[i] = fmt.Sprintf("%s = excluded.%s", field, field)
46 > }
47 > return fmt.Sprintf(
48 > // The WHERE clause ensures that no update occurs if the version is behind the saved version.
49 > "ON CONFLICT (namespace_id, run_id) DO UPDATE SET %s WHERE executions_visibility.%s < EXCLUDED.%s",
50 > strings.Join(items, ", "), sqlplugin.VersionColumnName, sqlplugin.VersionColumnName,
51 > )
52 }
53
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/typeconv.go 10 covered LOC · 6 ranges

Open complete file

18
19 // ToSQLiteDateTime converts to time to SQLite datetime
20 > func (c *converter) ToSQLiteDateTime(t time.Time) time.Time { typeconv.go
21 > if t.IsZero() {
22 return minSQLiteDateTime
23 }
24 > return t.UTC().Truncate(time.Microsecond) typeconv.go
25 }
26
27 // FromSQLiteDateTime converts SQLite datetime and returns go time
28 > func (c *converter) FromSQLiteDateTime(t time.Time) time.Time { typeconv.go
29 > if t.Equal(minSQLiteDateTime) {
30 return time.Time{}.UTC()
31 }
32 > return t.UTC() typeconv.go
33 }
34
35 > func getMinSQLiteDateTime() time.Time { typeconv.go
36 > t, err := time.Parse(time.RFC3339, "1000-01-01T00:00:00Z")
37 > if err != nil {
38 return time.Unix(0, 0).UTC()
39 }
40 > return t.UTC() typeconv.go
41 }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/visibility.go 10 covered LOC · 1 range

Open complete file

42 )
43
44 > func buildOnDuplicateKeyUpdate(fields ...string) string { visibility.go
45 > items := make([]string, len(fields))
46 > for i, field := range fields {
47 > items[i] = fmt.Sprintf("%s = excluded.%s", field, field)
48 > }
49 > return fmt.Sprintf(
50 > // The WHERE clause ensures that no update occurs if the version is behind the saved version.
51 > "ON CONFLICT (namespace_id, run_id) DO UPDATE SET %s WHERE executions_visibility.%s < EXCLUDED.%s",
52 > strings.Join(items, ", "), sqlplugin.VersionColumnName, sqlplugin.VersionColumnName,
53 > )
54 }
55
go.temporal.io/server/common/persistence/sql/sqlplugin/visibility.go 10 covered LOC · 2 ranges

Open complete file

219 }
220
221 > func getDbFields() []string { visibility.go
222 > t := reflect.TypeFor[VisibilityRow]()
223 > dbFields := make([]string, t.NumField())
224 > for i := 0; i < t.NumField(); i++ {
225 > f := t.Field(i)
226 > dbFields[i] = f.Tag.Get("db")
227 > if dbFields[i] == "" {
228 > dbFields[i] = strcase.ToSnake(f.Name)
229 > }
230 }
231 > return dbFields visibility.go
232 }
233
go.temporal.io/server/common/persistence/visibility/chasm_visibility_manager.go 10 covered LOC · 2 ranges

Open complete file

24 nsRegistry namespace.Registry,
25 visibilityMgr manager.VisibilityManager,
26 > ) *ChasmVisibilityManager { chasm_visibility_manager.go
27 > return &ChasmVisibilityManager{
28 > registry: registry,
29 > nsRegistry: nsRegistry,
30 > visibilityMgr: visibilityMgr,
31 > }
32 > }
33
34 func ChasmVisibilityManagerProvider(
36 nsRegistry namespace.Registry,
37 visibilityMgr manager.VisibilityManager,
38 > ) chasm.VisibilityManager { chasm_visibility_manager.go
39 > return NewChasmVisibilityManager(registry, nsRegistry, visibilityMgr)
40 > }
41
42 // ListExecutions implements the Engine interface for visibility queries.
go.temporal.io/server/common/persistence/visibility/store/query/util.go 10 covered LOC · 2 ranges

Open complete file

70 }
71
72 > func NewUnsafeSQLString(val string) *UnsafeSQLString { util.go
73 > return &UnsafeSQLString{Val: val}
74 > }
75
76 func NewColName(name string) *ColumnName {
78 }
79
80 > func NewSAColumn(alias string, fieldName string, valueType enumspb.IndexedValueType) *SAColumn { util.go
81 > return &SAColumn{
82 > Alias: alias,
83 > FieldName: fieldName,
84 > ValueType: valueType,
85 > }
86 > }
87
88 func NamespaceDivisionSAColumn() *SAColumn {
go.temporal.io/server/common/quotas/delayed_request_rate_limiter.go 10 covered LOC · 3 ranges

Open complete file

30 delay time.Duration,
31 timeSource clock.TimeSource,
32 > ) (*DelayedRequestRateLimiter, error) { delayed_request_rate_limiter.go
33 > if delay < 0 {
34 return nil, fmt.Errorf("%w: %v", ErrNegativeDelay, delay)
35 }
36
37 > delegator := RequestRateLimiterDelegator{} delayed_request_rate_limiter.go
38 > delegator.SetRateLimiter(NoopRequestRateLimiter)
39 >
40 > timer := timeSource.AfterFunc(delay, func() {
41 delegator.SetRateLimiter(rl)
42 })
43
44 > return &DelayedRequestRateLimiter{ delayed_request_rate_limiter.go
45 > RequestRateLimiter: &delegator,
46 > timer: timer,
47 > }, nil
48 }
49
go.temporal.io/server/common/quotas/request.go 10 covered LOC · 1 range

Open complete file

19 callerSegment int32,
20 initiation string,
21 > ) Request { request.go
22 > return Request{
23 > API: api,
24 > Token: token,
25 > Caller: caller,
26 > CallerType: callerType,
27 > CallerSegment: callerSegment,
28 > Initiation: initiation,
29 > }
30 > }
go.temporal.io/server/components/callbacks/executors.go 10 covered LOC · 2 ranges

Open complete file

25 registry *hsm.Registry,
26 executorOptions TaskExecutorOptions,
27 > ) error { executors.go
28 > exec := taskExecutor{executorOptions}
29 > if err := hsm.RegisterImmediateExecutor(
30 > registry,
31 > exec.executeInvocationTask,
32 > ); err != nil {
33 return err
34 }
35 > return hsm.RegisterTimerExecutor( executors.go
36 > registry,
37 > exec.executeBackoffTask,
38 > )
39 }
40
go.temporal.io/server/components/callbacks/tasks.go 10 covered LOC · 5 ranges

Open complete file

26 }
27
28 > func (InvocationTask) Type() string { tasks.go
29 > return TaskTypeInvocation
30 > }
31
32 func (t InvocationTask) Destination() string {
58 var _ hsm.Task = BackoffTask{}
59
60 > func (BackoffTask) Type() string { tasks.go
61 > return TaskTypeBackoff
62 > }
63
64 func (t BackoffTask) Deadline() time.Time {
84 }
85
86 > func RegisterTaskSerializers(reg *hsm.Registry) error { tasks.go
87 > if err := reg.RegisterTaskSerializer(TaskTypeInvocation, InvocationTaskSerializer{}); err != nil {
88 return err
89 }
90 > if err := reg.RegisterTaskSerializer(TaskTypeBackoff, BackoffTaskSerializer{}); err != nil { // nolint:revive tasks.go
91 return err
92 }
93 > return nil tasks.go
94 }
go.temporal.io/server/service/frontend/health_check.go 10 covered LOC · 1 range

Open complete file

49 healthCheckFn func(ctx context.Context, hostAddress string) (*historyservice.DeepHealthCheckResponse, error),
50 logger log.Logger,
51 > ) HealthChecker { health_check.go
52 > return &healthCheckerImpl{
53 > serviceName: serviceName,
54 > membershipMonitor: membershipMonitor,
55 > hostFailurePercentage: hostFailurePercentage,
56 > hostDeclinedServingProportion: hostDeclinedServingProportion,
57 > healthCheckFn: healthCheckFn,
58 > logger: logger,
59 > }
60 > }
61
62 func (h *healthCheckerImpl) Check(ctx context.Context) (HealthCheckResult, error) {
go.temporal.io/server/service/history/archival/archiver.go 10 covered LOC · 1 range

Open complete file

94 searchAttributeProvider searchattribute.Provider,
95 visibilityManger manager.VisibilityManager,
96 > ) Archiver { archiver.go
97 > return &archiver{
98 > archiverProvider: archiverProvider,
99 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.ArchiverClientScope)),
100 > logger: logger,
101 > rateLimiter: rateLimiter,
102 > searchAttributeProvider: searchAttributeProvider,
103 > visibilityManager: visibilityManger,
104 > }
105 > }
106
107 func (a *archiver) Archive(ctx context.Context, request *Request) (res *Response, err error) {
go.temporal.io/server/service/history/workflow/task_generator_provider.go 10 covered LOC · 3 ranges

Open complete file

23 )
24
25 > func init() { task_generator_provider.go
26 > var defaultProvider TaskGeneratorProvider = new(taskGeneratorProviderImpl)
27 > populateTaskGeneratorProvider(defaultProvider)
28 > }
29
30 > func populateTaskGeneratorProvider(provider TaskGeneratorProvider) { task_generator_provider.go
31 > _taskGeneratorProvider.Store(&provider)
32 > }
33
34 > func GetTaskGeneratorProvider() TaskGeneratorProvider { task_generator_provider.go
35 > return *_taskGeneratorProvider.Load()
36 > }
37
38 func (p *taskGeneratorProviderImpl) NewTaskGenerator(
go.temporal.io/server/chasm/lib/scheduler/generator_tasks.go 9 covered LOC · 1 range

Open complete file

38 )
39
40 > func NewGeneratorTaskHandler(opts GeneratorTaskHandlerOptions) *GeneratorTaskHandler { generator_tasks.go
41 > return &GeneratorTaskHandler{
42 > config: opts.Config,
43 > metricsHandler: opts.MetricsHandler,
44 > baseLogger: opts.BaseLogger,
45 > SpecProcessor: opts.SpecProcessor,
46 > specBuilder: opts.SpecBuilder,
47 > }
48 > }
49
50 func (g *GeneratorTaskHandler) Execute(
go.temporal.io/server/chasm/lib/scheduler/scheduler_migrate_task.go 9 covered LOC · 1 range

Open complete file

54 func NewSchedulerMigrateToWorkflowTaskHandler(
55 opts SchedulerMigrateToWorkflowTaskHandlerOptions,
56 > ) *SchedulerMigrateToWorkflowTaskHandler { scheduler_migrate_task.go
57 > return &SchedulerMigrateToWorkflowTaskHandler{
58 > config: opts.Config,
59 > metricsHandler: opts.MetricsHandler,
60 > baseLogger: opts.BaseLogger,
61 > historyClient: opts.HistoryClient,
62 > saMapperProvider: opts.SaMapperProvider,
63 > }
64 > }
65
66 func (h *SchedulerMigrateToWorkflowTaskHandler) Validate(
go.temporal.io/server/chasm/lib/workflow/config.go 9 covered LOC · 1 range

Open complete file

14 }
15
16 > func NewConfig(dc *dynamicconfig.Collection) Config { config.go
17 > return Config{
18 > maxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
19 > defaultWorkflowRetrySettings: dynamicconfig.DefaultWorkflowRetryPolicy.Get(dc),
20 > maxLinksPerRequest: dynamicconfig.FrontendMaxLinksPerRequest.Get(dc),
21 > linkMaxSize: dynamicconfig.FrontendLinkMaxSize.Get(dc),
22 > enableSignalWithStartFromWorkflow: dynamicconfig.EnableSignalWithStartFromWorkflow.Get(dc),
23 > }
24 > }
go.temporal.io/server/chasm/visibility.go 9 covered LOC · 1 range

Open complete file

64
65 // newVisibilitySearchAttributesMapper returns a mapper with all maps initialized.
66 > func newVisibilitySearchAttributesMapper() *VisibilitySearchAttributesMapper { visibility.go
67 > return &VisibilitySearchAttributesMapper{
68 > aliasToField: make(map[string]string),
69 > fieldToAlias: make(map[string]string),
70 > saTypeMap: make(map[string]enumspb.IndexedValueType),
71 > systemAliasToField: make(map[string]string),
72 > overriddenSystemFields: make(map[string]enumspb.IndexedValueType),
73 > }
74 > }
75
76 // Alias returns the alias for a given field.
go.temporal.io/server/client/history/redirector.go 9 covered LOC · 2 ranges

Open complete file

41 connections connectionPool[C],
42 historyServiceResolver membership.ServiceResolver,
43 > ) *BasicRedirector[C] { redirector.go
44 > return &BasicRedirector[C]{
45 > connections: connections,
46 > historyServiceResolver: historyServiceResolver,
47 > }
48 > }
49
50 > func (r *BasicRedirector[C]) Close() { redirector.go
51 > r.connections.Close()
52 > }
53
54 func (r *BasicRedirector[C]) clientForShardID(shardID int32) (C, error) {
go.temporal.io/server/client/matching/retryable_client_gen.go 9 covered LOC · 1 range

Open complete file

361 request *matchingservice.ListNexusEndpointsRequest,
362 opts ...grpc.CallOption,
363 > ) (*matchingservice.ListNexusEndpointsResponse, error) { retryable_client_gen.go
364 > var resp *matchingservice.ListNexusEndpointsResponse
365 > op := func(ctx context.Context) error {
366 > var err error
367 > resp, err = c.client.ListNexusEndpoints(ctx, request, opts...)
368 > return err
369 > }
370 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
371 > return resp, err
372 }
373
go.temporal.io/server/common/api/metadata.go 9 covered LOC · 3 ranges

Open complete file

217 // GetMethodMetadata gets metadata for a given API method in one of the services exported by
218 // frontend (WorkflowService, OperatorService, AdminService).
219 > func GetMethodMetadata(fullApiName string) MethodMetadata { metadata.go
220 > switch {
221 > case strings.HasPrefix(fullApiName, WorkflowServicePrefix):
222 > return workflowServiceMetadata[MethodName(fullApiName)]
223 case strings.HasPrefix(fullApiName, OperatorServicePrefix):
224 return operatorServiceMetadata[MethodName(fullApiName)]
233
234 // MethodName returns just the method name from a fully qualified name.
235 > func MethodName(fullApiName string) string { metadata.go
236 > index := strings.LastIndex(fullApiName, "/")
237 > if index > -1 {
238 > return fullApiName[index+1:] metadata.go
239 > }
240 return fullApiName
241 }
go.temporal.io/server/common/membership/hostinfo.go 9 covered LOC · 3 ranges

Open complete file

12
13 // NewHostInfoFromAddress creates a new HostInfo instance from a socket address.
14 > func NewHostInfoFromAddress(address string) HostInfo { hostinfo.go
15 > return hostAddress(address)
16 > }
17
18 // hostAddress is a HostInfo implementation that uses a string as the address and identity.
20
21 // GetAddress returns the value of the hostAddress.
22 > func (a hostAddress) GetAddress() string { hostinfo.go
23 > return string(a)
24 > }
25
26 // Identity returns the value of the hostAddress.
27 > func (a hostAddress) Identity() string { hostinfo.go
28 > return string(a)
29 > }
go.temporal.io/server/common/metrics/noop_impl.go 9 covered LOC · 5 ranges

Open complete file

15 )
16
17 > func newNoopMetricsHandler() *noopMetricsHandler { return &noopMetricsHandler{} } noop_impl.go
18
19 // WithTags creates a new MetricProvder with provided []Tag
29
30 // Gauge obtains a gauge for the given name.
31 > func (*noopMetricsHandler) Gauge(string) GaugeIface { noop_impl.go
32 > return NoopGaugeMetricFunc
33 > }
34
35 // Timer obtains a timer for the given name.
36 > func (*noopMetricsHandler) Timer(string) TimerIface { noop_impl.go
37 > return NoopTimerMetricFunc
38 > }
39
40 // Histogram obtains a histogram for the given name.
54
55 var NoopCounterMetricFunc = CounterFunc(func(i int64, t ...Tag) {})
56 > var NoopGaugeMetricFunc = GaugeFunc(func(f float64, t ...Tag) {}) noop_impl.go
57 > var NoopTimerMetricFunc = TimerFunc(func(d time.Duration, t ...Tag) {}) noop_impl.go
58 var NoopHistogramMetricFunc = HistogramFunc(func(i int64, t ...Tag) {})
go.temporal.io/server/common/persistence/sql/sqlplugin/util.go 9 covered LOC · 2 ranges

Open complete file

5 )
6
7 > func appendPrefix(prefix string, fields []string) []string { util.go
8 > out := make([]string, len(fields))
9 > for i, field := range fields {
10 > out[i] = prefix + field
11 > }
12 > return out
13 }
14
15 > func BuildNamedPlaceholder(fields ...string) string { util.go
16 > return strings.Join(appendPrefix(":", fields), ", ")
17 > }
go.temporal.io/server/common/persistence/task_manager.go 9 covered LOC · 2 ranges

Open complete file

27 store TaskStore,
28 serializer serialization.Serializer,
29 > ) TaskManager { task_manager.go
30 > return &taskManagerImpl{
31 > taskStore: store,
32 > serializer: serializer,
33 > }
34 > }
35
36 > func (m *taskManagerImpl) Close() { task_manager.go
37 > m.taskStore.Close()
38 > }
39
40 func (m *taskManagerImpl) GetName() string {
go.temporal.io/server/common/quotas/routing_rate_limiter_impl.go 9 covered LOC · 3 ranges

Open complete file

17 func NewRoutingRateLimiter(
18 apiToRateLimiter map[string]RequestRateLimiter,
19 > ) *RoutingRateLimiterImpl { routing_rate_limiter_impl.go
20 > return &RoutingRateLimiterImpl{
21 > apiToRateLimiter: apiToRateLimiter,
22 > }
23 > }
24
25 // Allow attempts to allow a request to go through. The method returns
go.temporal.io/server/common/rpc/context.go 9 covered LOC · 3 ranges

Open complete file

16 )
17
18 > func (c *valueCopyCtx) Value(key any) any { context.go
19 > if value := c.Context.Value(key); value != nil {
20 return value
21 }
22
23 > return c.valueCtx.Value(key) context.go
24 }
25
26 // CopyContextValues copies values in source Context to destination Context.
27 > func CopyContextValues(dst context.Context, src context.Context) context.Context { context.go
28 > return &valueCopyCtx{
29 > Context: dst,
30 > valueCtx: src,
31 > }
32 > }
33
34 // ResetContextTimeout creates new context with specified timeout and copies values from source Context.
go.temporal.io/server/common/rpc/interceptor/dc_redirection_policy.go 9 covered LOC · 3 ranges

Open complete file

91 namespaceRegistry namespace.Registry,
92 policy config.DCRedirectionPolicy,
93 > ) DCRedirectionPolicy { dc_redirection_policy.go
94 > switch policy.Policy {
95 case DCRedirectionPolicyDefault:
96 // default policy, noop
97 return NewNoopRedirectionPolicy(clusterMetadata.GetCurrentClusterName())
98 > case DCRedirectionPolicyNoop: dc_redirection_policy.go
99 > return NewNoopRedirectionPolicy(clusterMetadata.GetCurrentClusterName())
100 case DCRedirectionPolicySelectedAPIsForwarding:
101 currentClusterName := clusterMetadata.GetCurrentClusterName()
110
111 // NewNoopRedirectionPolicy is DC redirection policy which does nothing
112 > func NewNoopRedirectionPolicy(currentClusterName string) *NoopRedirectionPolicy { dc_redirection_policy.go
113 > return &NoopRedirectionPolicy{
114 > currentClusterName: currentClusterName,
115 > }
116 > }
117
118 // WithNamespaceIDRedirect redirect the API call based on namespace ID
go.temporal.io/server/components/nexusoperations/statemachine.go 9 covered LOC · 4 ranges

Open complete file

192 type operationMachineDefinition struct{}
193
194 > func (operationMachineDefinition) Type() string { statemachine.go
195 > return OperationMachineType
196 > }
197
198 func (operationMachineDefinition) Deserialize(d []byte) (any, error) {
488 }
489
490 > func (cancelationMachineDefinition) Type() string { statemachine.go
491 > return CancelationMachineType
492 > }
493
494 // CompareState compares the progress of two Cancelation state machines to determine whether to sync machine state while
675 )
676
677 > func RegisterStateMachines(r *hsm.Registry) error { statemachine.go
678 > if err := r.RegisterMachine(operationMachineDefinition{}); err != nil {
679 return err
680 }
681 > return r.RegisterMachine(cancelationMachineDefinition{}) statemachine.go
682 }
go.temporal.io/server/service/history/ndc/events_reapplier.go 9 covered LOC · 1 range

Open complete file

41 metricsHandler metrics.Handler,
42 logger log.Logger,
43 > ) *EventsReapplierImpl { events_reapplier.go
44 >
45 > return &EventsReapplierImpl{
46 > stateMachineRegistry: stateMachineRegistry,
47 > chasmWorkflowRegistry: chasmWorkflowRegistry,
48 > metricsHandler: metricsHandler,
49 > logger: logger,
50 > }
51 > }
52
53 func (r *EventsReapplierImpl) ReapplyEvents(
go.temporal.io/server/service/history/queues/active_standby_executor.go 9 covered LOC · 1 range

Open complete file

26 standbyExecutor Executor,
27 logger log.Logger,
28 > ) Executor { active_standby_executor.go
29 > return &activeStandbyExecutor{
30 > currentClusterName: currentClusterName,
31 > registry: registry,
32 > activeExecutor: activeExecutor,
33 > standbyExecutor: standbyExecutor,
34 > logger: logger,
35 > }
36 > }
37
38 func (e *activeStandbyExecutor) Execute(
go.temporal.io/server/service/history/queues/dlq_writer.go 9 covered LOC · 1 range

Open complete file

51 r namespace.Registry,
52 cr *chasm.Registry,
53 > ) *DLQWriter { dlq_writer.go
54 > return &DLQWriter{
55 > dlqWriter: w,
56 > metricsHandler: h,
57 > logger: l,
58 > namespaceRegistry: r,
59 > chasmRegistry: cr,
60 > }
61 > }
62
63 // WriteTaskToDLQ writes a task to the DLQ, creating the underlying queue if it doesn't already exist.
go.temporal.io/server/service/history/replication/progress_cache.go 9 covered LOC · 1 range

Open complete file

53 logger log.Logger,
54 handler metrics.Handler,
55 > ) ProgressCache { progress_cache.go
56 > maxSize := config.ReplicationProgressCacheMaxSize()
57 > opts := &cache.Options{
58 > TTL: config.ReplicationProgressCacheTTL(),
59 > }
60 > return &progressCacheImpl{
61 > cache: cache.NewWithMetrics(maxSize, opts, handler.WithTags(metrics.CacheTypeTag(metrics.ReplicationProgressCacheTypeTagValue))),
62 > }
63 > }
64
65 func (c *progressCacheImpl) Get(
go.temporal.io/server/service/history/replication/sync_state_retriever.go 9 covered LOC · 1 range

Open complete file

88 eventBlobCache persistence.XDCCache,
89 logger log.Logger,
90 > ) *SyncStateRetrieverImpl { sync_state_retriever.go
91 > return &SyncStateRetrieverImpl{
92 > shardContext: shardContext,
93 > workflowCache: workflowCache,
94 > workflowConsistencyChecker: workflowConsistencyChecker,
95 > eventBlobCache: eventBlobCache,
96 > logger: logger,
97 > }
98 > }
99
100 func (s *SyncStateRetrieverImpl) GetSyncWorkflowStateArtifact(
go.temporal.io/server/service/history/tasks/category.go 9 covered LOC · 3 ranges

Open complete file

96 }
97
98 > func (c Category) ID() int { category.go
99 > return c.id
100 > }
101
102 > func (c Category) Name() string { category.go
103 > return c.name
104 > }
105
106 > func (c Category) Type() CategoryType { category.go
107 > return c.cType
108 > }
109
110 func (c Category) MarshalText() (text []byte, err error) {
go.temporal.io/server/service/history/workflow/command_handler.go 9 covered LOC · 3 ranges

Open complete file

31
32 // NewCommandHandlerRegistry creates a new [CommandHandlerRegistry].
33 > func NewCommandHandlerRegistry() *CommandHandlerRegistry { command_handler.go
34 > return &CommandHandlerRegistry{
35 > handlers: make(map[enumspb.CommandType]CommandHandler),
36 > }
37 > }
38
39 // Register registers a [CommandHandler] for a given command type.
40 // Returns an [ErrDuplicateRegistration] if a handler for the given command is already registered.
41 // All registration is expected to happen in a single thread on process initialization.
42 > func (r *CommandHandlerRegistry) Register(t enumspb.CommandType, handler CommandHandler) error { command_handler.go
43 > if existing, ok := r.handlers[t]; ok {
44 return fmt.Errorf("%w: command handler for %v: %v", ErrDuplicateRegistration, t, existing)
45 }
46 > r.handlers[t] = handler command_handler.go
47 > return nil
48 }
49
go.temporal.io/server/temporaltest/options.go 9 covered LOC · 3 ranges

Open complete file

15 type applyFunc func(*TestServer)
16
17 > func (f applyFunc) apply(s *TestServer) { f(s) } options.go
18
19 // WithT directs all worker and client logs to the test logger.
21 // If this option is specified, then server will automatically be stopped when the
22 // test completes.
23 > func WithT(t *testing.T) TestServerOption { options.go
24 > return applyFunc(func(server *TestServer) {
25 > server.t = t
26 > })
27 }
28
46
47 // WithBaseServerOptions enables configuring additional server options not directly exposed via temporaltest.
48 > func WithBaseServerOptions(options ...temporal.ServerOption) TestServerOption { options.go
49 > return applyFunc(func(server *TestServer) {
50 > server.serverOptions = append(server.serverOptions, options...)
51 > })
52 }
go.temporal.io/server/chasm/lib/activity/fx.go 8 covered LOC · 2 ranges

Open complete file

21 newLibrary,
22 ),
23 > fx.Invoke(func(l *library, registry *chasm.Registry) error { fx.go
24 > return registry.Register(l)
25 > }),
26 )
27
34 fx.Provide(resource.SearchAttributeValidatorProvider),
35 fx.Provide(newComponentOnlyLibrary),
36 > fx.Invoke(func(l *componentOnlyLibrary, registry *chasm.Registry) error { fx.go
37 > // Frontend needs to register the component in order to serialize ComponentRefs, but doesn't
38 > // need task handlers.
39 > return registry.Register(l)
40 > }),
41 )
go.temporal.io/server/chasm/lib/callback/validator.go 8 covered LOC · 1 range

Open complete file

29 headerMaxSize dynamicconfig.IntPropertyFnWithNamespaceFilter,
30 endpointRules dynamicconfig.TypedPropertyFnWithNamespaceFilter[AddressMatchRules],
31 > ) Validator { validator.go
32 > return &validator{
33 > maxCallbacksPerExecution: maxCallbacksPerExecution,
34 > urlMaxLength: urlMaxLength,
35 > headerMaxSize: headerMaxSize,
36 > endpointRules: endpointRules,
37 > }
38 > }
39
40 // Validate validates completion callbacks: count, URL length, endpoint allowlist, header size, and normalizes header
go.temporal.io/server/chasm/lib/scheduler/backfiller_tasks.go 8 covered LOC · 1 range

Open complete file

36 )
37
38 > func NewBackfillerTaskHandler(opts BackfillerTaskHandlerOptions) *BackfillerTaskHandler { backfiller_tasks.go
39 > return &BackfillerTaskHandler{
40 > config: opts.Config,
41 > metricsHandler: opts.MetricsHandler,
42 > baseLogger: opts.BaseLogger,
43 > specProcessor: opts.SpecProcessor,
44 > }
45 > }
46
47 // BackfillerTask invalidation reasons. Limited cardinality for ReasonTag.
go.temporal.io/server/chasm/lib/scheduler/spec_processor.go 8 covered LOC · 1 range

Open complete file

66 logger log.Logger,
67 specBuilder *legacyscheduler.SpecBuilder,
68 > ) *SpecProcessorImpl { spec_processor.go
69 > return &SpecProcessorImpl{
70 > config: config,
71 > metricsHandler: metricsHandler,
72 > logger: logger,
73 > specBuilder: specBuilder,
74 > }
75 > }
76
77 func (s *SpecProcessorImpl) ProcessTimeRange(
go.temporal.io/server/chasm/lib/workflow/fx.go 8 covered LOC · 3 ranges

Open complete file

17 library *library,
18 config *nexusoperation.Config,
19 > ) error { fx.go
20 > if err := library.registry.Register(
21 > newNexusLibrary(config, chasmRegistry.NexusEndpointProcessor),
22 > ); err != nil {
23 return err
24 }
25 > return chasmRegistry.Register(library) fx.go
26 }),
27 )
30 // history service. Only include this in services that provide
31 // historyservice.HistoryServiceServer (the history service).
32 > var HistoryHandlerModule = fx.Invoke(func(library *library, historyHandler historyservice.HistoryServiceServer) { fx.go
33 > library.workflowServiceNexusHandler.setHistoryHandler(historyHandler)
34 > })
go.temporal.io/server/client/matching/client_gen.go 8 covered LOC · 3 ranges

Open complete file

406 request *matchingservice.ListNexusEndpointsRequest,
407 opts ...grpc.CallOption,
408 > ) (*matchingservice.ListNexusEndpointsResponse, error) { client_gen.go
409 >
410 > p, err := tqid.NormalPartitionFromRpcName("not-applicable", "not-applicable", enumspb.TASK_QUEUE_TYPE_UNSPECIFIED)
411 > if err != nil {
412 return nil, err
413 }
414
415 > client, err := c.getClientForTaskQueuePartition(p) client_gen.go
416 > if err != nil {
417 > return nil, err client_gen.go
418 > }
419 ctx, cancel := c.createLongPollContext(ctx)
420 defer cancel()
go.temporal.io/server/client/matching/retryable_client.go 8 covered LOC · 1 range

Open complete file

24 pollPolicy backoff.RetryPolicy,
25 isRetryable backoff.IsRetryable,
26 > ) matchingservice.MatchingServiceClient { retryable_client.go
27 > return &retryableClient{
28 > client: client,
29 > policy: policy,
30 > pollPolicy: pollPolicy,
31 > isRetryable: isRetryable,
32 > }
33 > }
34
35 func (c *retryableClient) Route(p tqid.Partition) (string, error) {
go.temporal.io/server/common/authorization/claim_mapper.go 8 covered LOC · 3 ranges

Open complete file

46 var _ ClaimMapperWithAuthInfoRequired = (*noopClaimMapper)(nil)
47
48 > func NewNoopClaimMapper() ClaimMapper { claim_mapper.go
49 > return &noopClaimMapper{}
50 > }
51
52 func (*noopClaimMapper) GetClaims(_ *AuthInfo) (*Claims, error) {
78 }
79
80 > func GetClaimMapperFromConfig(config *config.Authorization, logger log.Logger) (ClaimMapper, error) { claim_mapper.go
81 >
82 > switch strings.ToLower(config.ClaimMapper) {
83 > case "": claim_mapper.go
84 > return NewNoopClaimMapper(), nil
85 case "default":
86 return NewDefaultJWTClaimMapper(NewDefaultTokenKeyProvider(config, logger), config, logger), nil
go.temporal.io/server/common/membership/hostinfo_provider.go 8 covered LOC · 2 ranges

Open complete file

7 )
8
9 > func NewHostInfoProvider(hostInfo HostInfo) *hostInfoProvider { hostinfo_provider.go
10 > return &hostInfoProvider{
11 > hostInfo: hostInfo,
12 > }
13 > }
14
15 > func (hip *hostInfoProvider) HostInfo() HostInfo { hostinfo_provider.go
16 > return hip.hostInfo
17 > }
go.temporal.io/server/common/persistence/history_task_queue_manager.go 8 covered LOC · 2 ranges

Open complete file

50 queue QueueV2,
51 serializer serialization.Serializer,
52 > ) *HistoryTaskQueueManagerImpl { history_task_queue_manager.go
53 > return &HistoryTaskQueueManagerImpl{
54 > queue: queue,
55 > serializer: serializer,
56 > }
57 > }
58
59 func (m *HistoryTaskQueueManagerImpl) EnqueueTask(
224 }
225
226 > func (m HistoryTaskQueueManagerImpl) Close() { history_task_queue_manager.go
227 > }
228
229 // combineUnique combines the given strings into a single string by hashing the length of each string and the string
go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/visibility.go 8 covered LOC · 1 range

Open complete file

73 )
74
75 > func buildOnDuplicateKeyUpdate(fields ...string) string { visibility.go
76 > items := make([]string, len(fields))
77 > for i, field := range fields {
78 > // This line is to ensure that no update occurs (for any column) if the version is behind the saved version.
79 > items[i] = fmt.Sprintf("%v = IF(%v < VALUES(%v), VALUES(%v), %v)",
80 > field, sqlplugin.VersionColumnName, sqlplugin.VersionColumnName, field, field)
81 > }
82 > return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", strings.Join(items, ", "))
83 }
84
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/admin.go 8 covered LOC · 2 ranges

Open complete file

63
64 // Exec executes a sql statement
65 > func (mdb *db) Exec(stmt string, args ...any) error { admin.go
66 > _, err := mdb.db.Exec(stmt, args...)
67 > return err
68 > }
69
70 // ListTables returns a list of tables in this database
95
96 // CreateDatabase creates a database if it doesn't exist
97 > func (mdb *db) CreateDatabase(name string) error { admin.go
98 > // SQLite does not need to create database
99 > return nil
100 > }
101
102 // DropDatabase drops a database
go.temporal.io/server/common/searchattribute/mapper.go 8 covered LOC · 1 range

Open complete file

93 searchAttributesProvider Provider,
94 fallbackIndexName string,
95 > ) MapperProvider { mapper.go
96 > return &mapperProviderImpl{
97 > customMapper: customMapper,
98 > namespaceRegistry: namespaceRegistry,
99 > searchAttributesProvider: searchAttributesProvider,
100 > fallbackIndexName: fallbackIndexName,
101 > }
102 > }
103
104 func (m *mapperProviderImpl) GetMapper(nsName namespace.Name) (Mapper, error) {
go.temporal.io/server/common/stats/windowed_tdigest.go 8 covered LOC · 3 ranges

Open complete file

72 // So, if you want 300 seconds of history on an event that records 1k counts/sec, 3 10-second windows
73 // is fine.
74 > func NewWindowedTDigest(cfg WindowConfig) (TimeWindowedStats, error) { windowed_tdigest.go
75 > if cfg.WindowCount <= 0 {
76 return nil, errors.New("windowCount must be non-negative")
77 }
78 > if cfg.WindowSize.Milliseconds() <= 50 { windowed_tdigest.go
79 return nil, errors.New("probable misconfiguration detected: windowSize is too small, consider increasing it to at least 50ms")
80 }
81 > return &timeWindowedTDigest{ windowed_tdigest.go
82 > windows: make([]timedWindow, cfg.WindowCount),
83 > cfg: cfg,
84 > // mu and head both empty
85 > }, nil
86 }
87
go.temporal.io/server/common/tasks/priority.go 8 covered LOC · 2 ranges

Open complete file

59 )
60
61 > func (p Priority) String() string { priority.go
62 > s, ok := PriorityName[p]
63 > if ok {
64 > return s
65 > }
66 return strconv.Itoa(int(p))
67 }
77 func getPriority(
78 class, subClass Priority,
79 > ) Priority { priority.go
80 > return class | subClass
81 > }
go.temporal.io/server/common/workercommands/dispatcher.go 8 covered LOC · 1 range

Open complete file

67 metricsHandler metrics.Handler,
68 logger log.Logger,
69 > ) *Dispatcher { dispatcher.go
70 > return &Dispatcher{
71 > matchingClient: matchingClient,
72 > config: config,
73 > metricsHandler: metricsHandler,
74 > logger: logger,
75 > }
76 > }
77
78 func (d *Dispatcher) Execute(
go.temporal.io/server/components/callbacks/fx.go 8 covered LOC · 3 ranges

Open complete file

30 httpClientCache *cluster.FrontendHTTPClientCache,
31 logger log.Logger,
32 > ) (HTTPCallerProvider, error) { fx.go
33 > localClient, err := rpcFactory.CreateLocalFrontendHTTPClient()
34 > if err != nil {
35 return nil, fmt.Errorf("cannot create local frontend HTTP client: %w", err)
36 }
37 > defaultClient := &http.Client{} fx.go
38 > callbackTokenGenerator := commonnexus.NewCallbackTokenGenerator()
39 >
40 > m := collection.NewOnceMap(func(queuescommon.NamespaceIDAndDestination) HTTPCaller {
41 return func(r *http.Request) (*http.Response, error) {
42 return routeRequest(r,
51 }
52 })
53 > return m.Get, nil fx.go
54 }
go.temporal.io/server/components/nexusoperations/workflow/commands.go 8 covered LOC · 2 ranges

Open complete file

329 endpointRegistry commonnexus.EndpointRegistry,
330 config *nexusoperations.Config,
331 > ) error { commands.go
332 > h := commandHandler{
333 > config: config,
334 > endpointRegistry: endpointRegistry,
335 > nexusProcessor: chasmRegistry.NexusEndpointProcessor,
336 > }
337 > if err := reg.Register(enumspb.COMMAND_TYPE_SCHEDULE_NEXUS_OPERATION, h.HandleScheduleCommand); err != nil {
338 return err
339 }
340 > return reg.Register(enumspb.COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION, h.HandleCancelCommand) commands.go
341 }
342
go.temporal.io/server/service/history/replication/eventhandler/event_importer.go 8 covered LOC · 1 range

Open complete file

49 serializer serialization.Serializer,
50 logger log.Logger,
51 > ) EventImporter { event_importer.go
52 > return &eventImporterImpl{
53 > historyFetcher: historyFetcher,
54 > engineProvider: engineProvider,
55 > serializer: serializer,
56 > logger: logger,
57 > }
58 > }
59
60 //nolint:revive // cognitive complexity 30 (> max enabled 25)
go.temporal.io/server/service/history/replication/eventhandler/history_events_handler.go 8 covered LOC · 1 range

Open complete file

59 shardController shard.Controller,
60 logger log.Logger,
61 > ) HistoryEventsHandler { history_events_handler.go
62 > return &historyEventsHandlerImpl{
63 > clusterMetadata: clusterMetadata,
64 > eventImporter: eventImporter,
65 > shardController: shardController,
66 > logger: logger,
67 > }
68 > }
69
70 func (h *historyEventsHandlerImpl) HandleHistoryEvents(
go.temporal.io/server/service/history/replication/eventhandler/remote_history_paginated_fetcher.go 8 covered LOC · 1 range

Open complete file

77 serializer serialization.Serializer,
78 logger log.Logger,
79 > ) HistoryPaginatedFetcher { remote_history_paginated_fetcher.go
80 > return &HistoryPaginatedFetcherImpl{
81 > NamespaceRegistry: namespaceRegistry,
82 > ClientBean: clientBean,
83 > Serializer: serializer,
84 > Logger: logger,
85 > }
86 > }
87
88 func (n *HistoryPaginatedFetcherImpl) GetSingleWorkflowHistoryPaginatedIteratorInclusive(
go.temporal.io/server/service/history/workflow/cache/fx.go 8 covered LOC · 2 ranges

Open complete file

12 lc fx.Lifecycle,
13 cache Cache,
14 > ) { fx.go
15 > lc.Append(fx.Hook{
16 > OnStop: func(_ context.Context) error {
17 > ci, ok := cache.(*cacheImpl) fx.go
18 > if ok {
19 > ci.stop()
20 > }
21 > return nil
22 },
23 })
go.temporal.io/server/service/history/workflow_rebuilder.go 8 covered LOC · 1 range

Open complete file

53 workflowCache wcache.Cache,
54 logger log.Logger,
55 > ) *workflowRebuilderImpl { workflow_rebuilder.go
56 > return &workflowRebuilderImpl{
57 > shard: shard,
58 > workflowConsistencyChecker: api.NewWorkflowConsistencyChecker(shard, workflowCache),
59 > transaction: workflow.NewTransaction(shard),
60 > logger: logger,
61 > }
62 > }
63
64 func (r *workflowRebuilderImpl) rebuild(
go.temporal.io/server/service/matching/reachability.go 8 covered LOC · 1 range

Open complete file

304 reachabilityCacheOpenWFExecutionTTL,
305 reachabilityCacheClosedWFExecutionTTL time.Duration,
306 > ) reachabilityCache { reachability.go
307 > return reachabilityCache{
308 > openWFCache: cache.New(reachabilityCacheMaxSize, &cache.Options{TTL: reachabilityCacheOpenWFExecutionTTL}),
309 > closedWFCache: cache.New(reachabilityCacheMaxSize, &cache.Options{TTL: reachabilityCacheClosedWFExecutionTTL}),
310 > metricsHandler: handler,
311 > visibilityMgr: visibilityMgr,
312 > }
313 > }
314
315 // Get retrieves the Workflow Count existence value based on the query-string key.
go.temporal.io/server/service/worker/parentclosepolicy/client.go 8 covered LOC · 1 range

Open complete file

46 sdkClientFactory sdk.ClientFactory,
47 numWorkflows int,
48 > ) Client { client.go
49 > return &clientImpl{
50 > metricsHandler: metricsHandler,
51 > logger: logger,
52 > sdkClientFactory: sdkClientFactory,
53 > numWorkflows: numWorkflows,
54 > }
55 > }
56
57 func (c *clientImpl) SendParentClosePolicyRequest(ctx context.Context, request Request) error {
go.temporal.io/server/chasm/lib/activity/link_validator.go 7 covered LOC · 1 range

Open complete file

21 maxLinksPerComponent dynamicconfig.IntPropertyFnWithNamespaceFilter,
22 linkMaxSize dynamicconfig.IntPropertyFnWithNamespaceFilter,
23 > ) *linkValidator { link_validator.go
24 > return &linkValidator{
25 > maxLinksPerRequest: maxLinksPerRequest,
26 > maxLinksPerComponent: maxLinksPerComponent,
27 > linkMaxSize: linkMaxSize,
28 > }
29 > }
30
31 // ValidateRequest checks count, per-link size, and variant shape for the links
go.temporal.io/server/chasm/lib/workflow/validator.go 7 covered LOC · 1 range

Open complete file

41 saMapperProvider searchattribute.MapperProvider,
42 saValidator *searchattribute.Validator,
43 > ) *RequestValidator { validator.go
44 > return &RequestValidator{
45 > config: config,
46 > saMapperProvider: saMapperProvider,
47 > saValidator: saValidator,
48 > }
49 > }
50
51 func (v *RequestValidator) ValidateWorkflowID(
go.temporal.io/server/chasm/statemachine.go 7 covered LOC · 1 range

Open complete file

34 // The apply function is called after verifying the transition is possible but before setting the destination state,
35 // so it can inspect the current (source) state.
36 > func NewTransition[S comparable, SM StateMachine[S], E any](src []S, dst S, apply func(SM, MutableContext, E) error) Transition[S, SM, E] { statemachine.go
37 > return Transition[S, SM, E]{
38 > Sources: src,
39 > Destination: dst,
40 > apply: apply,
41 > }
42 > }
43
44 // Possible returns a boolean indicating whether the transition is possible for the current state.
go.temporal.io/server/client/admin/client.go 7 covered LOC · 1 range

Open complete file

33 largeTimeout time.Duration,
34 client adminservice.AdminServiceClient,
35 > ) adminservice.AdminServiceClient { client.go
36 > return &clientImpl{
37 > timeout: timeout,
38 > largeTimeout: largeTimeout,
39 > client: client,
40 > }
41 > }
42
43 func (c *clientImpl) createContext(parent context.Context) (context.Context, context.CancelFunc) {
go.temporal.io/server/client/admin/metric_client.go 7 covered LOC · 1 range

Open complete file

27 metricsHandler metrics.Handler,
28 throttledLogger log.Logger,
29 > ) adminservice.AdminServiceClient { metric_client.go
30 > return &metricClient{
31 > client: client,
32 > metricsHandler: metricsHandler,
33 > throttledLogger: throttledLogger,
34 > }
35 > }
36
37 func (c *metricClient) startMetricsRecording(
go.temporal.io/server/client/admin/retryable_client.go 7 covered LOC · 1 range

Open complete file

18
19 // NewRetryableClient creates a new instance of adminservice.AdminServiceClient with retry policy
20 > func NewRetryableClient(client adminservice.AdminServiceClient, policy backoff.RetryPolicy, isRetryable backoff.IsRetryable) adminservice.AdminServiceClient { retryable_client.go
21 > return &retryableClient{
22 > client: client,
23 > policy: policy,
24 > isRetryable: isRetryable,
25 > }
26 > }
27
28 func (c *retryableClient) StreamWorkflowReplicationMessages(
go.temporal.io/server/client/frontend/client.go 7 covered LOC · 1 range

Open complete file

32 longPollTimeout time.Duration,
33 client workflowservice.WorkflowServiceClient,
34 > ) workflowservice.WorkflowServiceClient { client.go
35 > return &clientImpl{
36 > timeout: timeout,
37 > longPollTimeout: longPollTimeout,
38 > client: client,
39 > }
40 > }
41
42 func (c *clientImpl) createContext(parent context.Context) (context.Context, context.CancelFunc) {
go.temporal.io/server/client/frontend/metric_client.go 7 covered LOC · 1 range

Open complete file

26 metricsHandler metrics.Handler,
27 throttledLogger log.Logger,
28 > ) workflowservice.WorkflowServiceClient { metric_client.go
29 > return &metricClient{
30 > client: client,
31 > metricsHandler: metricsHandler,
32 > throttledLogger: throttledLogger,
33 > }
34 > }
35
36 func (c *metricClient) startMetricsRecording(
go.temporal.io/server/client/frontend/retryable_client.go 7 covered LOC · 1 range

Open complete file

15
16 // NewRetryableClient creates a new instance of workflowservice.WorkflowServiceClient with retry policy
17 > func NewRetryableClient(client workflowservice.WorkflowServiceClient, policy backoff.RetryPolicy, isRetryable backoff.IsRetryable) workflowservice.WorkflowServiceClient { retryable_client.go
18 > return &retryableClient{
19 > client: client,
20 > policy: policy,
21 > isRetryable: isRetryable,
22 > }
23 > }
go.temporal.io/server/client/history/retryable_client.go 7 covered LOC · 1 range

Open complete file

18
19 // NewRetryableClient creates a new instance of historyservice.HistoryServiceClient with retry policy
20 > func NewRetryableClient(client historyservice.HistoryServiceClient, policy backoff.RetryPolicy, isRetryable backoff.IsRetryable) historyservice.HistoryServiceClient { retryable_client.go
21 > return &retryableClient{
22 > client: client,
23 > policy: policy,
24 > isRetryable: isRetryable,
25 > }
26 > }
27
28 func (c *retryableClient) StreamWorkflowReplicationMessages(
go.temporal.io/server/client/matching/metric_client_gen.go 7 covered LOC · 2 ranges

Open complete file

294 request *matchingservice.ListNexusEndpointsRequest,
295 opts ...grpc.CallOption,
296 > ) (_ *matchingservice.ListNexusEndpointsResponse, retError error) { metric_client_gen.go
297 >
298 > metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientListNexusEndpoints")
299 > defer func() {
300 > c.finishMetricsRecording(metricsHandler, startTime, retError)
301 > }()
302
303 > return c.client.ListNexusEndpoints(ctx, request, opts...) metric_client_gen.go
304 }
305
go.temporal.io/server/common/contextutil/metadata.go 7 covered LOC · 1 range

Open complete file

132
133 // WithMetadataContext adds a metadata context to the given context.
134 > func WithMetadataContext(ctx context.Context) context.Context { metadata.go
135 > metadataCtx := &metadataContext{
136 > Metadata: make(map[string]any),
137 > MarkedActivityIDs: make(map[string]struct{}),
138 > }
139 > return context.WithValue(ctx, metadataCtxKey, metadataCtx)
140 > }
141
142 // ContextHasMetadata returns true if the context has metadata support.
go.temporal.io/server/common/definition/workflow_key.go 7 covered LOC · 1 range

Open complete file

19 workflowID string,
20 runID string,
21 > ) WorkflowKey { workflow_key.go
22 > return WorkflowKey{
23 > NamespaceID: namespaceID,
24 > WorkflowID: workflowID,
25 > RunID: runID,
26 > }
27 > }
28
29 func (k *WorkflowKey) GetNamespaceID() string {
go.temporal.io/server/common/namespace/nsreplication/dlq_message_handler.go 7 covered LOC · 1 range

Open complete file

33 namespaceReplicationQueue persistence.NamespaceReplicationQueue,
34 logger log.Logger,
35 > ) DLQMessageHandler { dlq_message_handler.go
36 > return &dlqMessageHandlerImpl{
37 > replicationHandler: replicationHandler,
38 > namespaceReplicationQueue: namespaceReplicationQueue,
39 > logger: logger,
40 > }
41 > }
42
43 // Read reads namespace replication DLQ messages
go.temporal.io/server/common/persistence/cassandra/version_checker.go 7 covered LOC · 3 ranges

Open complete file

21 r resolver.ServiceResolver,
22 logger log.Logger,
23 > ) error { version_checker.go
24 > return checkMainKeyspace(cfg, r, logger)
25 > }
26
27 func checkMainKeyspace(
29 r resolver.ServiceResolver,
30 logger log.Logger,
31 > ) error { version_checker.go
32 > ds, ok := cfg.DataStores[cfg.DefaultStore]
33 > if ok && ds.Cassandra != nil {
34 return CheckCompatibleVersion(*ds.Cassandra, r, cassandraschema.Version, logger)
35 }
36 > return nil version_checker.go
37 }
38
go.temporal.io/server/common/persistence/data_blob.go 7 covered LOC · 2 ranges

Open complete file

8 // NewDataBlob returns a new DataBlob.
9 // TODO: return an UnknowEncodingType error with the actual type string when encodingTypeStr is invalid
10 > func NewDataBlob(data []byte, encodingTypeStr string) *commonpb.DataBlob { data_blob.go
11 > encodingType, err := enumspb.EncodingTypeFromString(encodingTypeStr)
12 > if err != nil {
13 // encodingTypeStr not valid, an error will be returned on deserialization
14 encodingType = enumspb.ENCODING_TYPE_UNSPECIFIED
15 }
16
17 > return &commonpb.DataBlob{ data_blob.go
18 > Data: data,
19 > EncodingType: encodingType,
20 > }
21 }
go.temporal.io/server/common/persistence/sql/task_v1.go 7 covered LOC · 1 range

Open complete file

34 logger log.Logger,
35 serializer serialization.Serializer,
36 > ) (*sqlTaskManagerV1, error) { task_v1.go
37 > return &sqlTaskManagerV1{
38 > SqlStore: NewSQLStore(db, logger, serializer),
39 > userDataStore: uds,
40 > taskQueueStore: tqs,
41 > }, nil
42 > }
43
44 func (m *sqlTaskManagerV1) CreateTasks(
go.temporal.io/server/common/persistence/sql/task_v2.go 7 covered LOC · 1 range

Open complete file

28 logger log.Logger,
29 serializer serialization.Serializer,
30 > ) (*sqlTaskManagerV2, error) { task_v2.go
31 > return &sqlTaskManagerV2{
32 > SqlStore: NewSQLStore(db, logger, serializer),
33 > userDataStore: uds,
34 > taskQueueStore: tqs,
35 > }, nil
36 > }
37
38 func (m *sqlTaskManagerV2) CreateTasks(
go.temporal.io/server/common/rpc/interceptor/request_error_handler.go 7 covered LOC · 1 range

Open complete file

45 logger log.Logger,
46 logAllReqErrors dynamicconfig.BoolPropertyFnWithNamespaceFilter,
47 > ) *RequestErrorHandler { request_error_handler.go
48 > return &RequestErrorHandler{
49 > logger: logger,
50 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
51 > logAllReqErrors: logAllReqErrors,
52 > }
53 > }
54
55 // HandleError handles error recording and logging
go.temporal.io/server/common/worker_versioning/routing_info_cache.go 7 covered LOC · 1 range

Open complete file

63
64 // NewRoutingInfoCache wraps the provided cache with a typed API and metrics.
65 > func NewRoutingInfoCache(c cache.Cache, metricsHandler metrics.Handler) RoutingInfoCache { routing_info_cache.go
66 > h := metricsHandler.WithTags(metrics.CacheTypeTag(metrics.RoutingInfoCacheTypeTagValue))
67 > return &RoutingInfoCacheImpl{
68 > Cache: c,
69 > metricsHandler: h,
70 > }
71 > }
72
73 func (c *RoutingInfoCacheImpl) Get(
go.temporal.io/server/common/worker_versioning/version_membership_cache.go 7 covered LOC · 1 range

Open complete file

63
64 // NewVersionMembershipAndReactivationStatusCache wraps the provided cache with a typed API and metrics.
65 > func NewVersionMembershipAndReactivationStatusCache(c cache.Cache, metricsHandler metrics.Handler) VersionMembershipAndReactivationStatusCache { version_membership_cache.go
66 > h := metricsHandler.WithTags(metrics.CacheTypeTag(metrics.VersionMembershipCacheTypeTagValue))
67 > return &VersionMembershipAndReactivationStatusCacheImpl{
68 > Cache: c,
69 > metricsHandler: h,
70 > }
71 > }
72
73 func (c *VersionMembershipAndReactivationStatusCacheImpl) Get(
go.temporal.io/server/service/history/hsm/sm.go 7 covered LOC · 1 range

Open complete file

41 // NewTransition creates a new [Transition] from the given source states to a destination state for a given event.
42 // The apply function is called after verifying the transition is possible and setting the destination state.
43 > func NewTransition[S comparable, SM StateMachine[S], E any](src []S, dst S, apply func(SM, E) (TransitionOutput, error)) Transition[S, SM, E] { sm.go
44 > return Transition[S, SM, E]{
45 > Sources: src,
46 > Destination: dst,
47 > apply: apply,
48 > }
49 > }
50
51 // Possible returns a boolean indicating whether the transition is possible for the current state.
go.temporal.io/server/service/history/queues/tracker.go 7 covered LOC · 1 range

Open complete file

18 )
19
20 > func newExecutableTracker(grouper Grouper) *executableTracker { tracker.go
21 > return &executableTracker{
22 > pendingExecutables: make(map[tasks.Key]Executable),
23 > grouper: grouper,
24 > pendingPerKey: make(map[any]int, 0),
25 > }
26 > }
27
28 func (t *executableTracker) split(
go.temporal.io/server/api/adminservice/v1/service_grpc.pb.go 6 covered LOC · 2 ranges

Open complete file

168 }
169
170 > func NewAdminServiceClient(cc grpc.ClientConnInterface) AdminServiceClient { service_grpc.pb.go
171 > return &adminServiceClient{cc}
172 > }
173
174 func (c *adminServiceClient) RebuildMutableState(ctx context.Context, in *RebuildMutableStateRequest, opts ...grpc.CallOption) (*RebuildMutableStateResponse, error) {
855 }
856
857 > func RegisterAdminServiceServer(s grpc.ServiceRegistrar, srv AdminServiceServer) { service_grpc.pb.go
858 > s.RegisterService(&AdminService_ServiceDesc, srv)
859 > }
860
861 func _AdminService_RebuildMutableState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
go.temporal.io/server/chasm/lib/nexusoperation/handler.go 6 covered LOC · 1 range

Open complete file

21 }
22
23 > func newHandler(config *Config, logger log.Logger) *handler { handler.go
24 > return &handler{
25 > config: config,
26 > logger: logger,
27 > }
28 > }
29
30 // StartNexusOperation creates a new standalone Nexus operation execution via CHASM.
go.temporal.io/server/chasm/lib/scheduler/handler.go 6 covered LOC · 1 range

Open complete file

22 }
23
24 > func newHandler(logger log.Logger, specBuilder *legacyscheduler.SpecBuilder) *handler { handler.go
25 > return &handler{
26 > logger: logger,
27 > specBuilder: specBuilder,
28 > }
29 > }
30
31 func (h *handler) CreateSchedule(ctx context.Context, req *schedulerpb.CreateScheduleRequest) (resp *schedulerpb.CreateScheduleResponse, err error) {
go.temporal.io/server/common/codec/jsonpb.go 6 covered LOC · 2 ranges

Open complete file

23
24 // NewJSONPBEncoder creates a new JSONPBEncoder.
25 > func NewJSONPBEncoder() JSONPBEncoder { jsonpb.go
26 > return JSONPBEncoder{}
27 > }
28
29 // NewJSONPBIndentEncoder creates a new JSONPBEncoder with indent.
37
38 // Encode protobuf struct to bytes.
39 > func (e JSONPBEncoder) Encode(pb proto.Message) ([]byte, error) { jsonpb.go
40 > return e.marshaler.Marshal(pb)
41 > }
42
43 // Decode bytes to protobuf struct.
go.temporal.io/server/common/collection/concurrent_tx_map.go 6 covered LOC · 1 range

Open complete file

55 //
56 // The hash function to use for sharding
57 > func NewShardedConcurrentTxMap(initialCap int, hashfn HashFunc) ConcurrentTxMap { concurrent_tx_map.go
58 > cmap := new(ShardedConcurrentTxMap)
59 > cmap.hashfn = hashfn
60 > cmap.initialCap = max(nShards, initialCap/nShards)
61 > return cmap
62 > }
63
64 // Get returns the value corresponding to the key, if it exist
go.temporal.io/server/common/collection/sync_map.go 6 covered LOC · 1 range

Open complete file

15 }
16
17 > func NewSyncMap[K comparable, V any]() SyncMap[K, V] { sync_map.go
18 > return SyncMap[K, V]{
19 > RWMutex: &sync.RWMutex{},
20 > contents: make(map[K]V),
21 > }
22 > }
23
24 func (m *SyncMap[K, V]) Get(key K) (value V, ok bool) {
go.temporal.io/server/common/dynamicconfig/fx.go 6 covered LOC · 2 ranges

Open complete file

8
9 var Module = fx.Options(
10 > fx.Provide(func(client Client, logger log.Logger, lc fx.Lifecycle) *Collection { fx.go
11 > col := NewCollection(client, logger)
12 > lc.Append(fx.StartStopHook(col.Start, col.Stop))
13 > return col
14 > }),
15 fx.Provide(fx.Annotate(
16 > func(c *Collection) pingable.Pingable { return c }, fx.go
17 fx.ResultTags(`group:"deadlockDetectorRoots"`),
18 )),
go.temporal.io/server/common/metrics/option.go 6 covered LOC · 2 ranges

Open complete file

10 type WithDescription string
11
12 > func (h WithDescription) apply(m *metricDefinition) { option.go
13 > m.description = string(h)
14 > }
15
16 // WithUnit sets the unit of a metric. See NewBytesHistogramDef for an example.
17 type WithUnit MetricUnit
18
19 > func (h WithUnit) apply(m *metricDefinition) { option.go
20 > m.unit = MetricUnit(h)
21 > }
go.temporal.io/server/common/namespace/nsreplication/transmission_task_handler.go 6 covered LOC · 1 range

Open complete file

44 namespaceReplicationQueue persistence.NamespaceReplicationQueue,
45 logger log.Logger,
46 > ) Replicator { transmission_task_handler.go
47 > return &replicator{
48 > namespaceReplicationQueue: namespaceReplicationQueue,
49 > logger: logger,
50 > }
51 > }
52
53 // HandleTransmissionTask handle transmission of the namespace replication task
go.temporal.io/server/common/persistence/cluster_metadata.go 6 covered LOC · 4 ranges

Open complete file

2
3 // GetOrUseDefaultActiveCluster return the current cluster name or use the input if valid
4 > func GetOrUseDefaultActiveCluster(currentClusterName string, activeClusterName string) string { cluster_metadata.go
5 > if len(activeClusterName) == 0 {
6 return currentClusterName
7 }
8 > return activeClusterName cluster_metadata.go
9 }
10
11 // GetOrUseDefaultClusters return the current cluster or use the input if valid
12 > func GetOrUseDefaultClusters(currentClusterName string, clusters []string) []string { cluster_metadata.go
13 > if len(clusters) == 0 {
14 return []string{currentClusterName}
15 }
16 > return clusters cluster_metadata.go
17 }
go.temporal.io/server/common/persistence/data_interfaces.go 6 covered LOC · 3 ranges

Open complete file

1408 // UnixMilliseconds returns t as a Unix time, the number of milliseconds elapsed since January 1, 1970 UTC.
1409 // It should be used for all CQL timestamp.
1410 > func UnixMilliseconds(t time.Time) int64 { data_interfaces.go
1411 > // Handling zero time separately because UnixNano is undefined for zero times.
1412 > if t.IsZero() {
1413 return 0
1414 }
1415
1416 > unixNano := t.UnixNano() data_interfaces.go
1417 > if unixNano < 0 {
1418 // Time is before January 1, 1970 UTC
1419 return 0
1420 }
1421 > return unixNano / int64(time.Millisecond) data_interfaces.go
1422 }
1423
go.temporal.io/server/common/persistence/nosql/nosqlplugin/cassandra/translator/fixed_address_translator.go 6 covered LOC · 2 ranges

Open complete file

15 )
16
17 > func init() { fixed_address_translator.go
18 > RegisterTranslator(fixedTranslatorName, NewFixedAddressTranslatorPlugin())
19 > }
20
21 type FixedAddressTranslatorPlugin struct {
22 }
23
24 > func NewFixedAddressTranslatorPlugin() TranslatorPlugin { fixed_address_translator.go
25 > return &FixedAddressTranslatorPlugin{}
26 > }
27
28 // GetTranslator What gocql driver does is that it will connect to the first node in the list in configuration
go.temporal.io/server/common/persistence/sql/execution.go 6 covered LOC · 1 range

Open complete file

30 logger log.Logger,
31 serializer serialization.Serializer,
32 > ) (p.ExecutionStore, error) { execution.go
33 > return &sqlExecutionStore{
34 > SqlStore: NewSQLStore(db, logger, serializer),
35 > HistoryBranchUtil: p.NewHistoryBranchUtil(serializer),
36 > }, nil
37 > }
38
39 // txExecuteShardLocked executes f under transaction and with read lock on shard row
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/nexus_endpoints.go 6 covered LOC · 2 ranges

Open complete file

32 }
33
34 > func (mdb *db) GetNexusEndpointsTableVersion(ctx context.Context) (int64, error) { nexus_endpoints.go
35 > var version int64
36 > err := mdb.conn.GetContext(ctx, &version, getEndpointsTableVersionQry)
37 > if errors.Is(err, sql.ErrNoRows) {
38 > return 0, nil nexus_endpoints.go
39 > }
40 return version, err
41 }
go.temporal.io/server/common/persistence/visibility/defs.go 6 covered LOC · 3 ranges

Open complete file

20 storeNames []string,
21 allowList dynamicconfig.BoolPropertyFnWithNamespaceFilter,
22 > ) dynamicconfig.BoolPropertyFnWithNamespaceFilter { defs.go
23 > if len(storeNames) == 0 {
24 return dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false)
25 }
26
27 > switch storeNames[0] { defs.go
28 > case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX, sqlite.PluginName: defs.go
29 > // Advanced visibility with SQL DB don't support list of values
30 > return dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false)
31 default:
32 // Otherwise (ES), check dynamic config
go.temporal.io/server/common/pprof/fx.go 6 covered LOC · 1 range

Open complete file

16 lc fx.Lifecycle,
17 pprof *PProfInitializerImpl,
18 > ) { fx.go
19 > lc.Append(
20 > fx.Hook{
21 > OnStart: func(context.Context) error {
22 > return pprof.Start()
23 > },
24 // todo: refactor pprof to gracefully shutdown http server
25 // OnStop: func(ctx context.Context) error {
go.temporal.io/server/common/predicates/universal.go 6 covered LOC · 2 ranges

Open complete file

5 )
6
7 > func Universal[T any]() Predicate[T] { universal.go
8 > return &UniversalImpl[T]{}
9 > }
10
11 func (a *UniversalImpl[T]) Test(t T) bool {
20 }
21
22 > func (*UniversalImpl[T]) Size() int { universal.go
23 > return EmptyPredicateProtoSize
24 > }
go.temporal.io/server/common/primitives/timestamp/time.go 6 covered LOC · 2 ranges

Open complete file

7 )
8
9 > func TimePtr(t time.Time) *timestamppb.Timestamp { time.go
10 > return timestamppb.New(t)
11 > }
12
13 func TimeValue(t *timestamppb.Timestamp) time.Time {
46 }
47
48 > func TimeNowPtrUtc() *timestamppb.Timestamp { time.go
49 > return TimePtr(time.Now().UTC())
50 > }
go.temporal.io/server/common/quotas/calculator/cluster_aware_quota_calculator.go 6 covered LOC · 3 ranges

Open complete file

32 // limit is used if and only if it is configured to a value greater than zero and the number of instances that
33 // the memberCounter reports is greater than zero. Otherwise, the per-instance limit is used.
34 > func getQuota(memberCounter MemberCounter, instanceLimit, clusterLimit int) float64 { cluster_aware_quota_calculator.go
35 > if clusterLimit > 0 && memberCounter != nil {
36 if clusterSize := memberCounter.AvailableMemberCount(); clusterSize > 0 {
37 return float64(clusterLimit) / float64(clusterSize)
39 }
40
41 > return float64(instanceLimit) cluster_aware_quota_calculator.go
42 }
43
44 > func (l ClusterAwareQuotaCalculator) GetQuota() float64 { cluster_aware_quota_calculator.go
45 > return getQuota(l.MemberCounter, l.PerInstanceQuota(), l.GlobalQuota())
46 > }
47
48 func (l ClusterAwareNamespaceQuotaCalculator) GetQuota(namespace string) float64 {
go.temporal.io/server/common/quotas/noop_reservation_impl.go 6 covered LOC · 2 ranges

Open complete file

14
15 // OK returns whether the limiter can provide the requested number of tokens
16 > func (r *NoopReservationImpl) OK() bool { noop_reservation_impl.go
17 > return true
18 > }
19
20 // Cancel indicates that the reservation holder will not perform the reserved action
38 // DelayFrom returns the duration for which the reservation holder must wait
39 // before taking the reserved action. Zero duration means act immediately.
40 > func (r *NoopReservationImpl) DelayFrom(_ time.Time) time.Duration { noop_reservation_impl.go
41 > return time.Duration(0) // no delay
42 > }
go.temporal.io/server/common/rpc/encryption/local_store_per_host_cert_provider_map.go 6 covered LOC · 1 range

Open complete file

22 refreshInterval time.Duration,
23 logger log.Logger,
24 > ) *localStorePerHostCertProviderMap { local_store_per_host_cert_provider_map.go
25 >
26 > providerMap := &localStorePerHostCertProviderMap{}
27 > if overrides == nil {
28 > return providerMap
29 > }
30
31 providerMap.certProviderCache = make(map[string]CertProvider, len(overrides))
go.temporal.io/server/common/rpc/interceptor/logtags/workflow_tags.go 6 covered LOC · 1 range

Open complete file

23 serializer *tasktoken.Serializer,
24 logger log.Logger,
25 > ) *WorkflowTags { workflow_tags.go
26 > return &WorkflowTags{
27 > serializer: serializer,
28 > logger: logger,
29 > }
30 > }
31
32 func (wt *WorkflowTags) Extract(req any, fullMethod string) []tag.Tag {
go.temporal.io/server/common/rpc/interceptor/routing_key_extractor_gen.go 6 covered LOC · 3 ranges

Open complete file

11 // from a WorkflowService request using field paths declared in the
12 // temporal.api.protometa.v1.request_header proto annotation.
13 > func workflowServiceRequestRoutingKey(req any) namespace.RoutingKey { routing_key_extractor_gen.go
14 > switch r := req.(type) {
15 case *workflowservice.CreateScheduleRequest:
16 return namespace.RoutingKey{ID: r.GetScheduleId()}
125 case *workflowservice.StartBatchOperationRequest:
126 return namespace.RoutingKey{ID: r.GetJobId()}
127 > case *workflowservice.StartWorkflowExecutionRequest: routing_key_extractor_gen.go
128 > return namespace.RoutingKey{ID: r.GetWorkflowId()}
129 case *workflowservice.StopBatchOperationRequest:
130 return namespace.RoutingKey{ID: r.GetJobId()}
157 case *workflowservice.UpdateWorkflowExecutionRequest:
158 return namespace.RoutingKey{ID: r.GetWorkflowExecution().GetWorkflowId()}
160 > return namespace.RoutingKey{}
161 }
162 }
go.temporal.io/server/common/wideevents/events.go 6 covered LOC · 1 range

Open complete file

25 // as an instrumentation-scope attribute (OTEL semconv service.name) so every emitted event carries
26 // it, replacing per-event common-tag plumbing.
27 > func NewLogger(lp log.LoggerProvider, serviceName string) log.Logger { events.go
28 > return lp.Logger(
29 > instrumentationName,
30 > log.WithInstrumentationAttributes(attribute.String("service.name", serviceName)),
31 > )
32 > }
33
34 // NoopLogger returns a logger that discards all events. Safe default for tests and for
go.temporal.io/server/components/callbacks/statemachine.go 6 covered LOC · 2 ranges

Open complete file

130 type stateMachineDefinition struct{}
131
132 > func (stateMachineDefinition) Type() string { statemachine.go
133 > return StateMachineType
134 > }
135
136 func (stateMachineDefinition) Deserialize(d []byte) (any, error) {
179 }
180
181 > func RegisterStateMachine(r *hsm.Registry) error { statemachine.go
182 > return r.RegisterMachine(stateMachineDefinition{})
183 > }
184
185 // EventScheduled is triggered when the callback is meant to be scheduled for the first time - when its Trigger
go.temporal.io/server/service/history/api/consistency_checker.go 6 covered LOC · 1 range

Open complete file

84 shardContext historyi.ShardContext,
85 workflowCache wcache.Cache,
86 > ) *WorkflowConsistencyCheckerImpl { consistency_checker.go
87 > return &WorkflowConsistencyCheckerImpl{
88 > shardContext: shardContext,
89 > workflowCache: workflowCache,
90 > }
91 > }
92
93 func (c *WorkflowConsistencyCheckerImpl) GetWorkflowCache() wcache.Cache {
go.temporal.io/server/service/history/configs/task.go 6 covered LOC · 1 range

Open complete file

26 func ConvertWeightsToDynamicConfigValue(
27 weights map[tasks.Priority]int,
28 > ) map[string]any { task.go
29 > weightsForDC := make(map[string]any)
30 > for priority, weight := range weights {
31 > weightsForDC[priority.String()] = weight
32 > }
33 > return weightsForDC
34 }
35
go.temporal.io/server/service/history/replication/poller_manager.go 6 covered LOC · 1 range

Open complete file

24 currentShardId int32,
25 clusterMetadata cluster.Metadata,
26 > ) *pollerManagerImpl { poller_manager.go
27 > return &pollerManagerImpl{
28 > currentShardId: currentShardId,
29 > clusterMetadata: clusterMetadata,
30 > }
31 > }
32
33 func (p pollerManagerImpl) getSourceClusterShardIDs(sourceClusterName string) ([]int32, error) {
go.temporal.io/server/service/history/workflow/relocatable_attributes_fetcher.go 6 covered LOC · 1 range

Open complete file

33 config *configs.Config,
34 visibilityManager manager.VisibilityManager,
35 > ) RelocatableAttributesFetcher { relocatable_attributes_fetcher.go
36 > return &relocatableAttributesFetcher{
37 > visibilityManager: visibilityManager,
38 > disableFetchFromVisibility: config.DisableFetchRelocatableAttributesFromVisibility,
39 > }
40 > }
41
42 // RelocatableAttributes contains workflow attributes that can be moved from the mutable state to the persistence
go.temporal.io/server/service/history/workflow/state_machine_definition.go 6 covered LOC · 2 ranges

Open complete file

29 }
30
31 > func (stateMachineDefinition) Type() string { state_machine_definition.go
32 > return StateMachineType
33 > }
34
35 > func RegisterStateMachine(reg *hsm.Registry) error { state_machine_definition.go
36 > return reg.RegisterMachine(stateMachineDefinition{})
37 > }
go.temporal.io/server/service/history/workflow/task_refresher.go 6 covered LOC · 1 range

Open complete file

55 func NewTaskRefresher(
56 shard historyi.ShardContext,
57 > ) *TaskRefresherImpl { task_refresher.go
58 > return &TaskRefresherImpl{
59 > shard: shard,
60 > taskGeneratorProvider: GetTaskGeneratorProvider(),
61 > }
62 > }
63
64 func (r *TaskRefresherImpl) Refresh(
go.temporal.io/server/service/history/workflow/transaction_impl.go 6 covered LOC · 1 range

Open complete file

40 func NewTransaction(
41 shardContext historyi.ShardContext,
42 > ) *TransactionImpl { transaction_impl.go
43 > return &TransactionImpl{
44 > shard: shardContext,
45 > logger: shardContext.GetLogger(),
46 > }
47 > }
48
49 func (t *TransactionImpl) CreateWorkflowExecution(
go.temporal.io/server/chasm/lib/scheduler/util.go 5 covered LOC · 1 range

Open complete file

26
27 // serializeConflictToken serializes a conflict token as a byte slice.
28 > func serializeConflictToken(conflictToken int64) []byte { util.go
29 > token := make([]byte, 8)
30 > binary.LittleEndian.PutUint64(token, uint64(conflictToken))
31 > return token
32 > }
33
34 // newTaggedLogger returns a logger tagged with the Scheduler's attributes.
go.temporal.io/server/common/authorization/authorizer.go 5 covered LOC · 2 ranges

Open complete file

62 }
63
64 > func GetAuthorizerFromConfig(config *config.Authorization) (Authorizer, error) { authorizer.go
65 >
66 > switch strings.ToLower(config.Authorizer) {
67 > case "": authorizer.go
68 > return NewNoopAuthorizer(), nil
69 case "default":
70 return NewDefaultAuthorizer(), nil
go.temporal.io/server/common/collection/priority_queue.go 5 covered LOC · 1 range

Open complete file

15 func NewPriorityQueue[T any](
16 compareLess func(this T, other T) bool,
17 > ) Queue[T] { priority_queue.go
18 > return &priorityQueueImpl[T]{
19 > compareLess: compareLess,
20 > }
21 > }
22
23 // NewPriorityQueueWithItems creats a new priority queue
go.temporal.io/server/common/metrics/registry.go 5 covered LOC · 1 range

Open complete file

43
44 // register adds a metric definition to the list of pending metric definitions. This method is thread-safe.
45 > func (c *registry) register(d metricDefinition) { registry.go
46 > c.Lock()
47 > defer c.Unlock()
48 > c.definitions = append(c.definitions, d)
49 > }
50
51 // buildCatalog builds a catalog from the list of pending metric definitions. It is safe to call this method multiple
go.temporal.io/server/common/namespace/nsmanager/attr_validator.go 5 covered LOC · 1 range

Open complete file

19 func NewValidator(
20 clusterMetadata cluster.Metadata,
21 > ) *Validator { attr_validator.go
22 > return &Validator{
23 > clusterMetadata: clusterMetadata,
24 > }
25 > }
26
27 func (d *Validator) ValidateNamespaceConfig(config *persistencespb.NamespaceConfig) error {
go.temporal.io/server/common/nexus/trace.go 5 covered LOC · 1 range

Open complete file

72 }
73
74 > func NewLoggedHTTPClientTraceProvider(dc *dynamicconfig.Collection) HTTPClientTraceProvider { trace.go
75 > return &LoggedHTTPClientTraceProvider{
76 > Config: HTTPTraceConfig.Get(dc),
77 > }
78 > }
79
80 func (p *LoggedHTTPClientTraceProvider) NewTrace(attempt int32, logger log.Logger) *httptrace.ClientTrace {
go.temporal.io/server/common/persistence/history_branch_util.go 5 covered LOC · 1 range

Open complete file

41 )
42
43 > func NewHistoryBranchUtil(serializer serialization.Serializer) *HistoryBranchUtilImpl { history_branch_util.go
44 > return &HistoryBranchUtilImpl{
45 > serializer: serializer,
46 > }
47 > }
48
49 func (u *HistoryBranchUtilImpl) NewHistoryBranch(
go.temporal.io/server/common/persistence/sql/queue_v2.go 5 covered LOC · 1 range

Open complete file

37 logger log.Logger,
38 serializer serialization.Serializer,
39 > ) persistence.QueueV2 { queue_v2.go
40 > return &queueV2{
41 > SqlStore: NewSQLStore(db, logger, serializer),
42 > }
43 > }
44
45 func (q *queueV2) EnqueueMessage(
go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/plugin.go 5 covered LOC · 1 range

Open complete file

24 var _ sqlplugin.Plugin = (*plugin)(nil)
25
26 > func init() { plugin.go
27 > sql.RegisterPlugin(PluginName, &plugin{
28 > queryConverter: &queryConverter{},
29 > })
30 > }
31
32 func (p *plugin) GetVisibilityQueryConverter() sqlplugin.VisibilityQueryConverter {
go.temporal.io/server/service/frontend/overrides.go 5 covered LOC · 1 range

Open complete file

15 }
16
17 > func NewOverrides() *Overrides { overrides.go
18 > return &Overrides{
19 > minTypeScriptEagerActivitySupportedVersion: semver.MustParse("1.4.4"),
20 > }
21 > }
22
23 func (o *Overrides) shouldForceDisableEagerDispatch(sdkName, sdkVersion string) bool {
go.temporal.io/server/service/history/chasm_notifier.go 5 covered LOC · 1 range

Open complete file

21
22 // NewChasmNotifier creates a new instance of ChasmNotifier.
23 > func NewChasmNotifier() *ChasmNotifier { chasm_notifier.go
24 > return &ChasmNotifier{
25 > executions: make(map[chasm.ExecutionKey]*subscriptionTracker),
26 > }
27 > }
28
29 // Subscribe returns a channel that will be closed when there is a notification relating to the
go.temporal.io/server/service/history/circuitbreakerpool/circuit_breaker_factory.go 5 covered LOC · 1 range

Open complete file

16 func NewCircuitBreakerPool[K comparable](
17 constructor func(key K) circuitbreaker.TwoStepCircuitBreaker,
18 > ) *CircuitBreakerPool[K] { circuit_breaker_factory.go
19 > return &CircuitBreakerPool[K]{
20 > m: collection.NewOnceMap(constructor),
21 > }
22 > }
go.temporal.io/server/service/history/replication/executable_task_converter.go 5 covered LOC · 1 range

Open complete file

27 func NewExecutableTaskConverter(
28 processToolBox ProcessToolBox,
29 > ) *executableTaskConverterImpl { executable_task_converter.go
30 > return &executableTaskConverterImpl{
31 > processToolBox: processToolBox,
32 > }
33 > }
34
35 func (e *executableTaskConverterImpl) Convert(
go.temporal.io/server/service/matching/rate_limit_fraction_provider.go 5 covered LOC · 2 ranges

Open complete file

26
27 // NewTaskQueueRateLimitFractionProvider wraps inner and enforces [0.0, 1.0] on every call.
28 > func NewTaskQueueRateLimitFractionProvider(inner TaskQueueRateLimitFractionProvider) TaskQueueRateLimitFractionProvider { rate_limit_fraction_provider.go
29 > return TaskQueueRateLimitFractionProviderFunc(func(nsName namespace.Name, tqName string, tqType enumspb.TaskQueueType) float64 {
30 return max(min(inner.GetRateLimitFraction(nsName, tqName, tqType), maxRateLimitFraction), minRateLimitFraction)
31 })
40 var defaultTaskQueueRateLimitFractionProvider = NewTaskQueueRateLimitFractionProvider(&unitRateLimitFractionProvider{})
41
42 > func taskQueueRateLimitFractionProviderProvider() TaskQueueRateLimitFractionProvider { rate_limit_fraction_provider.go
43 > return defaultTaskQueueRateLimitFractionProvider
44 > }
go.temporal.io/server/chasm/lib/callback/config.go 4 covered LOC · 1 range

Open complete file

44 }
45
46 > func configProvider(dc *dynamicconfig.Collection) *Config { config.go
47 > return &Config{
48 > RequestTimeout: RequestTimeout.Get(dc),
49 > RetryPolicy: func() backoff.RetryPolicy {
50 return backoff.NewExponentialRetryPolicy(
51 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/common/authorization/frontend_api.go 4 covered LOC · 1 range

Open complete file

23 }
24
25 > func IsHealthCheckAPI(fullApi string) bool { frontend_api.go
26 > _, found := healthCheckAPI[fullApi]
27 > return found
28 > }
go.temporal.io/server/common/log/with_logger.go 4 covered LOC · 2 ranges

Open complete file

14 // With returns Logger instance that prepend every log entry with tags. If logger implements
15 // WithLogger it is used, otherwise every log call will be intercepted.
16 > func With(logger Logger, tags ...tag.Tag) Logger { with_logger.go
17 > if wl, ok := logger.(WithLogger); ok {
18 > return wl.With(tags...) with_logger.go
19 > }
20 return newWithLogger(logger, tags...)
21 }
go.temporal.io/server/common/metrics/metrics.go 4 covered LOC · 4 ranges

Open complete file

80 )
81
82 > func (c CounterFunc) Record(v int64, tags ...Tag) { c(v, tags...) } metrics.go
83 > func (c GaugeFunc) Record(v float64, tags ...Tag) { c(v, tags...) } metrics.go
84 > func (c TimerFunc) Record(v time.Duration, tags ...Tag) { c(v, tags...) } metrics.go
85 > func (c HistogramFunc) Record(v int64, tags ...Tag) { c(v, tags...) } metrics.go
go.temporal.io/server/common/persistence/noop_health_signal_aggregator.go 4 covered LOC · 4 ranges

Open complete file

go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/typeconv.go 4 covered LOC · 2 ranges

Open complete file

33 }
34
35 > func getMinMySQLDateTime() time.Time { typeconv.go
36 > t, err := time.Parse(time.RFC3339, "1000-01-01T00:00:00Z")
37 > if err != nil {
38 return time.Unix(0, 0).UTC()
39 }
40 > return t.UTC() typeconv.go
41 }
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/typeconv.go 4 covered LOC · 2 ranges

Open complete file

35 }
36
37 > func getMinPostgreSQLDateTime() time.Time { typeconv.go
38 > t, err := time.Parse(time.RFC3339, "1000-01-01T00:00:00Z")
39 > if err != nil {
40 return time.Unix(0, 0).UTC()
41 }
42 > return t.UTC() typeconv.go
43 }
go.temporal.io/server/components/callbacks/config.go 4 covered LOC · 1 range

Open complete file

38 }
39
40 > func ConfigProvider(dc *dynamicconfig.Collection) *Config { config.go
41 > return &Config{
42 > RequestTimeout: RequestTimeout.Get(dc),
43 > RetryPolicy: func() backoff.RetryPolicy {
44 return backoff.NewExponentialRetryPolicy(
45 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/service/history/circuitbreakerpool/fx.go 4 covered LOC · 1 range

Open complete file

22 namespaceRegistry namespace.Registry,
23 config *configs.Config,
24 > ) *OutboundQueueCircuitBreakerPool { fx.go
25 > return &OutboundQueueCircuitBreakerPool{
26 > CircuitBreakerPool: NewCircuitBreakerPool(
27 > func(key tasks.TaskGroupNamespaceIDAndDestination) circuitbreaker.TwoStepCircuitBreaker {
28 // This is intentionally not failing the function in case of error. The circuit breaker is
29 // agnostic to Task implementation, and thus the settings function is not expected to return
go.temporal.io/server/api/historyservice/v1/service_grpc.pb.go 3 covered LOC · 1 range

Open complete file

1652 }
1653
1654 > func RegisterHistoryServiceServer(s grpc.ServiceRegistrar, srv HistoryServiceServer) { service_grpc.pb.go
1655 > s.RegisterService(&HistoryService_ServiceDesc, srv)
1656 > }
1657
1658 func _HistoryService_StartWorkflowExecution_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
go.temporal.io/server/api/matchingservice/v1/service_grpc.pb.go 3 covered LOC · 1 range

Open complete file

971 }
972
973 > func RegisterMatchingServiceServer(s grpc.ServiceRegistrar, srv MatchingServiceServer) { service_grpc.pb.go
974 > s.RegisterService(&MatchingService_ServiceDesc, srv)
975 > }
976
977 func _MatchingService_PollWorkflowTaskQueue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
go.temporal.io/server/api/persistence/v1/predicates.go-helpers.pb.go 3 covered LOC · 1 range

Open complete file

17
18 // Size returns the size of the object, in bytes, once serialized
19 > func (val *Predicate) Size() int { predicates.go-helpers.pb.go
20 > return proto.Size(val)
21 > }
22
23 // Equal returns whether two Predicate values are equivalent by recursively
go.temporal.io/server/chasm/fx.go 3 covered LOC · 1 range

Open complete file

6 "chasm",
7 fx.Provide(NewRegistry),
8 > fx.Invoke(func(registry *Registry) error { fx.go
9 > return registry.Register(&CoreLibrary{})
10 > }),
11 )
go.temporal.io/server/chasm/lib/tests/fx.go 3 covered LOC · 1 range

Open complete file

10 var Module = fx.Module(
11 "chasm.lib.tests",
12 > fx.Invoke(func(registry *chasm.Registry) error { fx.go
13 > return registry.Register(Library)
14 > }),
15 )
go.temporal.io/server/chasm/visibility_manager.go 3 covered LOC · 1 range

Open complete file

166 ctx context.Context,
167 engine VisibilityManager,
168 > ) context.Context { visibility_manager.go
169 > return context.WithValue(ctx, visibilityManagerCtxKey, engine)
170 > }
171
172 func visibilityManagerFromContext(
go.temporal.io/server/common/authorization/noop_authorizer.go 3 covered LOC · 1 range

Open complete file

6
7 // NewNoopAuthorizer creates a no-op authorizer
8 > func NewNoopAuthorizer() Authorizer { noop_authorizer.go
9 > return &noopAuthorizer{}
10 > }
11
12 func (a *noopAuthorizer) Authorize(_ context.Context, _ *Claims, _ *CallTarget) (Result, error) {
go.temporal.io/server/common/deadlock/fx.go 3 covered LOC · 1 range

Open complete file

7 var Module = fx.Options(
8 fx.Provide(NewDeadlockDetector),
9 > fx.Invoke(func(lc fx.Lifecycle, dd *deadlockDetector) { fx.go
10 > lc.Append(fx.StartStopHook(dd.Start, dd.Stop))
11 > }),
12 )
go.temporal.io/server/common/dynamicconfig/key.go 3 covered LOC · 1 range

Open complete file

13 )
14
15 > func MakeKey(s string) Key { key.go
16 > return Key{handle: unique.Make(strings.ToLower(s))}
17 > }
18
19 func (k Key) String() string {
go.temporal.io/server/common/dynamicconfig/static_client.go 3 covered LOC · 2 ranges

Open complete file

10 )
11
12 > func (s StaticClient) GetValue(key Key) []ConstrainedValue { static_client.go
13 > if v, ok := s[key]; ok {
14 if cvs, ok := v.([]ConstrainedValue); ok {
15 return cvs
17 return []ConstrainedValue{{Value: v}}
18 }
19 > return nil static_client.go
20 }
21
go.temporal.io/server/common/namespace/nsregistry/fx.go 3 covered LOC · 1 range

Open complete file

13 lc fx.Lifecycle,
14 registry namespace.Registry,
15 > ) { fx.go
16 > lc.Append(fx.StartStopHook(registry.Start, registry.Stop))
17 > }
go.temporal.io/server/common/namespace/nsreplication/data_merger.go 3 covered LOC · 1 range

Open complete file

12
13 // NewNoopDataMerger creates a new NoopDataMerger.
14 > func NewNoopDataMerger() NamespaceDataMerger { data_merger.go
15 > return &NoopDataMerger{}
16 > }
17
18 // MergeData returns taskData directly without any merging.
go.temporal.io/server/common/namespace/nsreplication/replication_admitter.go 3 covered LOC · 1 range

Open complete file

19
20 // NewDefaultAdmitter creates the default NamespaceReplicationAdmitter.
21 > func NewDefaultAdmitter() NamespaceReplicationAdmitter { replication_admitter.go
22 > return &DefaultAdmitter{}
23 > }
24
25 // Admit returns true iff currentCluster appears in the task's replication
go.temporal.io/server/common/nexus/callback_token.go 3 covered LOC · 1 range

Open complete file

33 }
34
35 > func NewCallbackTokenGenerator() *CallbackTokenGenerator { callback_token.go
36 > return &CallbackTokenGenerator{}
37 > }
38
39 func (g *CallbackTokenGenerator) Tokenize(completion *tokenspb.NexusOperationCompletion) (string, error) {
go.temporal.io/server/common/nexus/nexusrpc/failure_converter.go 3 covered LOC · 1 range

Open complete file

196 // [Failure] instances are converted to [FailureError] to allow access to the full failure metadata and details if
197 // available.
198 > func DefaultFailureConverter() FailureConverter { failure_converter.go
199 > return defaultFailureConverter
200 > }
201
202 func retryBehaviorAsOptionalBool(e *nexus.HandlerError) *bool {
go.temporal.io/server/common/payload/payload.go 3 covered LOC · 1 range

Open complete file

30 }
31
32 > func Encode(value any) (*commonpb.Payload, error) { payload.go
33 > return defaultDataConverter.ToPayload(value)
34 > }
35
36 func Decode(p *commonpb.Payload, valuePtr any) error {
go.temporal.io/server/common/persistence/json_history_token_serializer.go 3 covered LOC · 1 range

Open complete file

23
24 // newJSONHistoryTokenSerializer creates a new instance of TaskTokenSerializer
25 > func newJSONHistoryTokenSerializer() *jsonHistoryTokenSerializer { json_history_token_serializer.go
26 > return &jsonHistoryTokenSerializer{}
27 > }
28
29 func (t *historyPagingToken) SetRangeIndexes(
go.temporal.io/server/common/persistence/nosql/nosqlplugin/cassandra/translator/translator_plugin.go 3 covered LOC · 1 range

Open complete file

22 // RegisterPlugin adds an auth plugin to the plugin registry
23 // it is only safe to use from a package init function
24 > func RegisterTranslator(name string, plugin TranslatorPlugin) { translator_plugin.go
25 > translators[name] = plugin
26 > }
27
28 func LookupTranslator(name string) (TranslatorPlugin, error) {
go.temporal.io/server/common/quotas/noop_request_rate_limiter_impl.go 3 covered LOC · 1 range

Open complete file

go.temporal.io/server/common/quotas/request_rate_limiter_delegator.go 3 covered LOC · 1 range

Open complete file

24
25 // SetRateLimiter sets the rate limiter to delegate to.
26 > func (d *RequestRateLimiterDelegator) SetRateLimiter(rl RequestRateLimiter) { request_rate_limiter_delegator.go
27 > d.delegate.Store(monomorphicRequestRateLimiter{rl})
28 > }
29
30 // loadDelegate returns the rate limiter that this rate limiter delegates to.
go.temporal.io/server/common/resolver/noop_resolver.go 3 covered LOC · 1 range

Open complete file

6 )
7
8 > func NewNoopResolver() *NoopResolver { noop_resolver.go
9 > return &NoopResolver{}
10 > }
11
12 func (c *NoopResolver) Resolve(service string) []string {
go.temporal.io/server/common/serviceerror/stale_partition_counts.go 3 covered LOC · 1 range

Open complete file

16
17 // NewStalePartitionCounts returns new StalePartitionCounts error.
18 > func NewStalePartitionCounts(message string) error { stale_partition_counts.go
19 > return &StalePartitionCounts{Message: message}
20 > }
21
22 // Error returns string message.
go.temporal.io/server/common/tasktoken/serializer.go 3 covered LOC · 1 range

Open complete file

9
10 // NewSerializer creates a new instance of Serializer
11 > func NewSerializer() *Serializer { serializer.go
12 > return &Serializer{}
13 > }
14
15 func (s *Serializer) Serialize(taskToken *tokenspb.Task) ([]byte, error) {
go.temporal.io/server/components/nexusoperations/completion.go 3 covered LOC · 1 range

Open complete file

174
175 // NewCompletionHandler returns a CompletionHandler. Wired via fx; see Module.
176 > func NewCompletionHandler(metricsHandler metrics.Handler, config *Config) *CompletionHandler { completion.go
177 > return &CompletionHandler{metricsHandler: metricsHandler, config: config}
178 > }
179
180 // Handle resolves an async Nexus operation completion.
go.temporal.io/server/components/nexusoperations/fx.go 3 covered LOC · 1 range

Open complete file

15 fx.Invoke(RegisterExecutor),
16 // Bridge CHASM ClientProvider to HSM ClientProvider type.
17 > fx.Provide(func(cp chasmnexus.ClientProvider) ClientProvider { fx.go
18 > return ClientProvider(cp)
19 > }),
20 )
21
go.temporal.io/server/service/history/archival/fx.go 3 covered LOC · 1 range

Open complete file

9 var Module = fx.Options(
10 fx.Provide(NewArchiver),
11 > fx.Provide(func(config *configs.Config) quotas.RateLimiter { fx.go
12 > return quotas.NewDefaultOutgoingRateLimiter(quotas.RateFn(config.ArchivalBackendMaxRPS))
13 > }),
14 )
go.temporal.io/server/service/history/events/fx.go 3 covered LOC · 1 range

Open complete file

10
11 var Module = fx.Options(
12 > fx.Provide(func(executionManager persistence.ExecutionManager, config *configs.Config, handler metrics.Handler, logger log.Logger) Cache { fx.go
13 > return NewHostLevelEventsCache(executionManager, config, handler, logger, false)
14 > }),
15 )
go.temporal.io/server/service/history/queues/errors/errors.go 3 covered LOC · 1 range

Open complete file

39
40 // NewUnprocessableTaskError returns a new UnprocessableTaskError from given message.
41 > func NewUnprocessableTaskError(message string) *UnprocessableTaskError { errors.go
42 > return &UnprocessableTaskError{Message: message}
43 > }
44
45 func (e UnprocessableTaskError) Error() string {
go.temporal.io/server/service/matching/simple_partition_scaler.go 3 covered LOC · 1 range

Open complete file

24 }
25
26 > func newSimplePartitionScalerFactory(cfg scalerFactoryCfg) *simplePartitionScalerFactory { simple_partition_scaler.go
27 > return &simplePartitionScalerFactory{cfg: cfg}
28 > }
29
30 func (s *simplePartitionScalerFactory) New(
go.temporal.io/server/service/worker/common/fx.go 3 covered LOC · 1 range

Open complete file

10 // AnnotateWorkerComponentProvider converts a WorkerComponent factory function into an fx provider which will add the
11 // WorkerComponentTag to the result.
12 > func AnnotateWorkerComponentProvider[T any](f func(t T) WorkerComponent) fx.Option { fx.go
13 > return fx.Provide(fx.Annotate(f, fx.ResultTags(WorkerComponentTag)))
14 > }
go.temporal.io/server/temporal/server.go 3 covered LOC · 1 range

Open complete file

42
43 // NewServer returns a new instance of server that serves one or many services.
44 > func NewServer(opts ...ServerOption) (Server, error) { server.go
45 > return NewServerFx(TopLevelModule, opts...)
46 > }
go.temporal.io/server/common/log/panic.go 2 covered LOC · 1 range

Open complete file

13 // We have to use pointer is because in golang: "recover return nil if was not called directly by a deferred function."
14 // And we have to set the returned error otherwise our handler will return nil as error which is incorrect
15 > func CapturePanic(logger Logger, retError *error) { panic.go
16 > if panicObj := recover(); panicObj != nil {
17 err, ok := panicObj.(error)
18 if !ok {
go.temporal.io/server/common/aggregate/noop_moving_window_average.go 1 covered LOC · 1 range

Open complete file

7 )
8
9 > func newNoopMovingWindowAverage() *noopMovingWindowAverage { return &noopMovingWindowAverage{} } noop_moving_window_average.go
10
11 func (a *noopMovingWindowAverage) Record(_ int64) {}