|
18 | 18 | // resources. It maintains relationships between different resource types and notifies |
19 | 19 | // handlers when resources or their relationships change. |
20 | 20 | // |
21 | | -// Lock Hierarchy |
| 21 | +// # Lock Hierarchy |
22 | 22 | // |
23 | 23 | // To prevent deadlocks, locks must be acquired in the following order: |
24 | 24 | // |
|
50 | 50 | // - Protects: nodeUpdateHandler, relationUpdateHandler |
51 | 51 | // - Independent - can be acquired anytime |
52 | 52 | // |
53 | | -// Threading Model |
| 53 | +// # Threading Model |
54 | 54 | // |
55 | 55 | // This package uses multiple goroutines for concurrent processing. Understanding the |
56 | 56 | // threading model is essential for avoiding race conditions and deadlocks. |
57 | 57 | // |
58 | 58 | // 1. Informer Threads (External): |
59 | | -// - Source: Kubernetes informers (one per resource type) |
60 | | -// - Entry points: nodeStorage.OnAdd, OnUpdate, OnDelete |
61 | | -// - Purpose: Receives resource change events from API server |
62 | | -// - Lock behavior: Acquires metaLock.Lock() during updateNodeMeta(), relationsLock during relation updates |
63 | | -// - Note: These are the ONLY threads that write to metaLock (labels, ownerRefs, objectExisted) |
| 59 | +// - Source: Kubernetes informers (one per resource type) |
| 60 | +// - Entry points: nodeStorage.OnAdd, OnUpdate, OnDelete |
| 61 | +// - Purpose: Receives resource change events from API server |
| 62 | +// - Lock behavior: Acquires metaLock.Lock() during updateNodeMeta(), relationsLock during relation updates |
| 63 | +// - Note: These are the ONLY threads that write to metaLock (labels, ownerRefs, objectExisted) |
64 | 64 | // |
65 | 65 | // 2. Event Processor Threads (Internal): |
66 | | -// - Source: Created by Start() -> startHandleEvent() |
67 | | -// - Count: 2 goroutines |
68 | | -// - handleNodeEvent(): Processes node add/update/delete/relatedUpdate events |
69 | | -// - handleRelationEvent(): Processes relation add/delete events |
70 | | -// - Trigger: newNodeEvent(), newRelationEvent() queue events via workqueue |
71 | | -// - Lock behavior: Read-only access to handlers via RLock, no direct node locking |
72 | | -// - Note: Reads handlers while holding no locks - relies on handlersLock for registration |
| 66 | +// - Source: Created by Start() -> startHandleEvent() |
| 67 | +// - Count: 2 goroutines |
| 68 | +// - handleNodeEvent(): Processes node add/update/delete/relatedUpdate events |
| 69 | +// - handleRelationEvent(): Processes relation add/delete events |
| 70 | +// - Trigger: newNodeEvent(), newRelationEvent() queue events via workqueue |
| 71 | +// - Lock behavior: Read-only access to handlers via RLock, no direct node locking |
| 72 | +// - Note: Reads handlers while holding no locks - relies on handlersLock for registration |
73 | 73 | // |
74 | 74 | // 3. User/Client Threads (External): |
75 | | -// - Source: User code calling Manager methods |
76 | | -// - Examples: GetNode(), GetTopoNodeStorage(), AddNodeHandler() |
77 | | -// - Lock behavior: Uses storagesLock.RLock() for reads |
78 | | -// - Note: These are typically short-lived operations |
| 75 | +// - Source: User code calling Manager methods |
| 76 | +// - Examples: GetNode(), GetTopoNodeStorage(), AddNodeHandler() |
| 77 | +// - Lock behavior: Uses storagesLock.RLock() for reads |
| 78 | +// - Note: These are typically short-lived operations |
79 | 79 | // |
80 | 80 | // 4. Callback Threads (External - via Event Processors): |
81 | | -// - Source: User-provided NodeHandler and RelationHandler callbacks |
82 | | -// - Entry: Called by handleNodeEvent/handleRelationEvent |
83 | | -// - Execution: Each callback runs in its own goroutine with a configurable timeout |
84 | | -// (ManagerConfig.EventHandlerTimeout, default 1s). If a callback does not return |
85 | | -// within the timeout, a warning is logged and all remaining handlers for that |
86 | | -// event are skipped. |
87 | | -// - Lock behavior: No resourcetopo locks held during callback execution |
88 | | -// - Concurrency: Multiple callbacks (across different handlers or events) may run |
89 | | -// concurrently. Handler implementations that share mutable state must be |
90 | | -// thread-safe. |
91 | | -// - Safety: Handlers receive node references but should not cache them long-term |
92 | | -// |
93 | | -// Thread Safety Guidelines |
94 | | -// |
95 | | -// - NodeInfo references returned by GetNode() are safe for concurrent reads |
96 | | -// - Do NOT call AddTopologyConfig() after Start() - not thread safe |
97 | | -// - Handler registration (AddNodeHandler, AddRelationHandler) is thread safe |
98 | | -// - Callbacks (OnAdd, OnUpdate, etc.) run in goroutines with a timeout. |
99 | | -// Do not block indefinitely — timed-out callbacks cause remaining handlers |
100 | | -// to be skipped. Implementations must be thread-safe if they share state. |
101 | | -// - nodeInfo.lock can be held for extended periods during relation changes |
102 | | -// - metaLock is never held during callbacks or cross-node operations |
103 | | -// |
| 81 | +// - Source: User-provided NodeHandler and RelationHandler callbacks |
| 82 | +// - Entry: Called by handleNodeEvent/handleRelationEvent |
| 83 | +// - Execution: Each callback runs in its own goroutine with a configurable timeout |
| 84 | +// (ManagerConfig.EventHandlerTimeout, default 1s). If a callback does not return |
| 85 | +// within the timeout, a warning is logged and all remaining handlers for that |
| 86 | +// event are skipped. |
| 87 | +// - Lock behavior: No resourcetopo locks held during callback execution |
| 88 | +// - Concurrency: Multiple callbacks (across different handlers or events) may run |
| 89 | +// concurrently. Handler implementations that share mutable state must be |
| 90 | +// thread-safe. |
| 91 | +// - Safety: Handlers receive node references but should not cache them long-term |
| 92 | +// |
| 93 | +// # Thread Safety Guidelines |
| 94 | +// |
| 95 | +// - NodeInfo references returned by GetNode() are safe for concurrent reads |
| 96 | +// - Do NOT call AddTopologyConfig() after Start() - not thread safe |
| 97 | +// - Handler registration (AddNodeHandler, AddRelationHandler) is thread safe |
| 98 | +// - Callbacks (OnAdd, OnUpdate, etc.) run in goroutines with a timeout. |
| 99 | +// Do not block indefinitely — timed-out callbacks cause remaining handlers |
| 100 | +// to be skipped. Implementations must be thread-safe if they share state. |
| 101 | +// - nodeInfo.lock can be held for extended periods during relation changes |
| 102 | +// - metaLock is never held during callbacks or cross-node operations |
104 | 103 | package resourcetopo |
0 commit comments