escalate

package
v5.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package escalate finds database call sites that must become domain commands when a handle moves off-thread (plan item P3.15b).

Moving a database to a worker changes what a call site can be. An in-process Query returns a cursor over a live connection; an off-thread one cannot, because there is no connection on this side. Every call site has to become a command — a named operation the worker performs — and that is a design decision per site, not a mechanical rewrite.

So this is an ASSISTANT and explicitly NOT A CODEMOD, which the plan states outright. It finds the sites, says what each one appears to do, and proposes a signature. A human writes the body. The reason is not caution for its own sake: a rewrite that mechanically wrapped each Query in a command would produce one command per call site, which is a chatty protocol with the same round-trip problem the move was meant to solve. Deciding which sites collapse into one command is the actual work, and a tool cannot do it.

What the tool CAN do reliably is find every site and refuse to guess about the ones it cannot read.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Access

type Access string

Access classifies what a call site does to the database.

const (
	// AccessRead only reads.
	AccessRead Access = "read"
	// AccessWrite modifies data or schema.
	AccessWrite Access = "write"
	// AccessUnknown means the SQL could not be read at this call site — it is
	// built at runtime, or comes from a variable or a constant elsewhere.
	//
	// Reported as its own class rather than guessed at. A write misclassified as
	// a read becomes a command the caller believes is safe to retry, and the
	// whole point of classifying is to inform exactly that decision.
	AccessUnknown Access = "unknown"
)

func ClassifySQL

func ClassifySQL(parseSQL string) Access

ClassifySQL reports whether a statement reads or writes.

Exported because it is useful on its own, and because it is the piece most worth testing directly: a write misclassified as a read becomes a command a caller believes is safe to retry.

type Finding

type Finding struct {
	// File and Line locate the call.
	File string
	Line int
	// Method is the method called: Query, QueryRow, or Exec.
	Method string
	// Receiver is the expression the method was called on, as written.
	Receiver string
	// SQL is the literal statement, empty when it could not be read.
	SQL string
	// Access classifies the statement.
	Access Access
	// ArgCount is the number of bind parameters passed.
	ArgCount int
	// ProposedCommand is a suggested command name derived from the statement.
	ProposedCommand string
	// ProposedSignature is a suggested Go declaration for the command.
	ProposedSignature string
	// NeedsHuman marks a site the tool could not classify, so a reviewer knows
	// which findings are information and which are questions.
	NeedsHuman bool
	// Note explains a NeedsHuman finding.
	Note string
}

Finding is one call site that must become a command.

func AnalyzeSource

func AnalyzeSource(parseFileName string, parseSource string, parseOptions Options) ([]Finding, error)

AnalyzeSource finds escalation sites in one Go source file.

Source text rather than a path so the analysis is testable without fixtures on disk and usable on unsaved buffers in an editor.

type Options

type Options struct {
	// Receivers restricts findings to calls on these receiver expressions, as
	// written in the source — "db", "s.db", "app.store".
	//
	// Empty means every receiver, which is the honest default for a first pass:
	// over-reporting is a reviewer's afternoon, and under-reporting is a call
	// site that silently keeps blocking the render thread.
	Receivers []string
}

Options configure an analysis.

type Summary

type Summary struct {
	Total      int
	Reads      int
	Writes     int
	NeedsHuman int
}

Summary describes an analysis run.

func Summarize

func Summarize(parseFindings []Finding) Summary

Summarize counts findings by class.

The NeedsHuman count is the one that matters for planning a migration: it is the number of sites a person has to read, as opposed to review.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL