mirror of
https://github.com/hashicorp/terraform.git
synced 2026-03-21 10:00:09 -04:00
55 lines
2.7 KiB
Go
55 lines
2.7 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
// Package promising is a utility package providing a model for concurrent
|
|
// data fetching and preparation which can detect and report deadlocks
|
|
// and failure to resolve.
|
|
//
|
|
// This is based on the structure and algorithms introduced by Caleb Voss and
|
|
// Vivek Sarkar of Georgia Institute of Technology in arXiv:2101.01312v1
|
|
// "An Ownership Policy and Deadlock Detector for Promises".
|
|
//
|
|
// The model includes both promises and tasks, where tasks can wait for and
|
|
// resolve promises and each promise has a single task that is responsbile
|
|
// for resolving it. Only explicit tasks can interact with promises, and the
|
|
// system uses that rule to detect incorrect situations such as:
|
|
//
|
|
// - Mutual dependency, where one task blocks on a promise owned by another
|
|
// and vice-versa.
|
|
// - Failure to resolve, where the task responsible for resolving a promise
|
|
// completes before it does so.
|
|
//
|
|
// Mutual dependency is assumed to be the result of invalid user input where
|
|
// two objects rely on each others results, and so that situation is reported
|
|
// in a way that can allow describing the problem to an end-user.
|
|
//
|
|
// Failure to resolve is always an implementation error: a task should always
|
|
// either resolve all promises it owns or pass ownership to some other task
|
|
// before it completes.
|
|
//
|
|
// This system cannot detect situations not directly related to promise and task
|
|
// relationships. For example, if a particular task blocks forever for a
|
|
// non-promise-related reason then that can still cause an effective deadlock
|
|
// of the overall system. Callers should design their usage of tasks carefully
|
|
// so that e.g. tasks also respond to context cancellation/deadlines.
|
|
//
|
|
// Package promising uses [context.Context] values to represent dynamic task
|
|
// scope, so callers must take care to use the contexts provided to task
|
|
// functions by this package (or children of those contexts) when performing
|
|
// any task-related or promise-related actions. This implicit behavior is not
|
|
// ideal but is a pragmatic tradeoff to help keep task identity aligned with
|
|
// other cross-cutting concerns that can travel in contexts, such as loggers
|
|
// and distributed tracing clients.
|
|
//
|
|
// Internally the task-related and promise-related operations implicitly
|
|
// construct a directed bipartite graph. Between tasks and promises the
|
|
// edges represent "awaiting", and between promises and tasks the edges
|
|
// represent which task is currently responsible for resolving each promise.
|
|
// Self-dependency is therefore detected by noticing when a call to a
|
|
// [PromiseGet] would form a cycle in the graph, and immediately returning an
|
|
// error in that case to avoid deadlocking the system.
|
|
package promising
|
|
|
|
import (
|
|
_ "context"
|
|
)
|