diff --git a/docs/doc-comments-prompt.txt b/docs/doc-comments-prompt.txt new file mode 100644 index 0000000..d283c09 --- /dev/null +++ b/docs/doc-comments-prompt.txt @@ -0,0 +1,59 @@ +Always start documentation comments with the symbol name verbatim, and then use this to start a sentence summarizing the symbol's function + +For documentation comments on functions and methods: + +- Write a general description in one or two sentences at the top + +- use the format `# Header` for headings of sections. + +- Follow by a description of the parameters and then return values, with a series of bullet points describing each item, each with an empty line in between. + +- Last, describe the expected behaviour of the function or method, keep this with one space apart from the comment start token + +For documentation on types, variables and comments, write 1-2 sentences describing how the item is used. + +For documentation on package, summarise in up to 3 sentences the functions and purpose of the package + +Do not use markdown ** or __ or any similar things in initial words of a bullet point, instead use standard godoc style # prefix for header sections + +ALWAYS separate each bullet point with an empty line, and ALWAYS indent them three spaces after the // + +NEVER put a colon after the first word of the first line of a document comment + +Use British English spelling and Oxford commas + +Always break lines before 80 columns, and flow under bullet points two columns right of the bullet point hyphen. + +Do not write a section for parameters or return values when there is none + +In the `# Expected behavior` section always add an empty line after this title before the description, and don't indent this section as this makes it appear as preformatted monospace. + +A good typical example: + +// NewServer initializes and returns a new Server instance based on the provided +// ServerParams and optional settings. It sets up storage, initializes the +// relay, and configures necessary components for server operation. +// +// # Parameters +// +// - sp (*ServerParams): The configuration parameters for initializing the +// server. +// +// - opts (...options.O): Optional settings that modify the server's behavior. +// +// # Return Values +// +// - s (*Server): The newly created Server instance. +// +// - err (error): An error if any step fails during initialization. +// +// # Expected Behaviour +// +// - Initializes storage with the provided database path. +// +// - Configures the server's options using the default settings and applies any +// optional settings provided. +// +// - Sets up a ServeMux for handling HTTP requests. +// +// - Initializes the relay, starting its operation in a separate goroutine. diff --git a/pkg/app/config/config.go b/pkg/app/config/config.go index 7ba6192..d11993e 100644 --- a/pkg/app/config/config.go +++ b/pkg/app/config/config.go @@ -44,7 +44,7 @@ type C struct { // New creates and initializes a new configuration object for the relay // application // -// Return values: +// # Return Values // // - cfg: A pointer to the initialized configuration struct containing default // or environment-provided values @@ -52,7 +52,7 @@ type C struct { // - err: An error object that is non-nil if any operation during // initialization fails // -// Expected behaviour: +// # Expected Behaviour: // // Initializes a new configuration instance by loading environment variables and // checking for a .env file in the default configuration directory. Sets logging @@ -92,12 +92,12 @@ func New() (cfg *C, err error) { // HelpRequested determines if the command line arguments indicate a request for help // -// Return values: +// # Return Values // // - help: A boolean value indicating true if a help flag was detected in the // command line arguments, false otherwise // -// Expected behaviour: +// # Expected Behaviour: // // The function checks the first command line argument for common help flags and // returns true if any of them are present. Returns false if no help flag is found @@ -114,12 +114,12 @@ func HelpRequested() (help bool) { // GetEnv checks if the first command line argument is "env" and returns // whether the environment configuration should be printed. // -// Return values: +// # Return Values // // - requested: A boolean indicating true if the 'env' argument was // provided, false otherwise. // -// Expected behaviour: +// # Expected Behaviour: // // The function returns true when the first command line argument is "env" // (case-insensitive), signalling that the environment configuration should be @@ -149,16 +149,16 @@ func (kv KVSlice) Swap(i, j int) { kv[i], kv[j] = kv[j], kv[i] } // Compose merges two KVSlice instances into a new slice where key-value pairs // from the second slice override any duplicate keys from the first slice. // -// Parameters: +// # Parameters // // - kv2: The second KVSlice whose entries will be merged with the receiver. // -// Return values: +// # Return Values // // - out: A new KVSlice containing all entries from both slices, with keys // from kv2 taking precedence over keys from the receiver. // -// Expected behaviour: +// # Expected Behaviour: // // The method returns a new KVSlice that combines the contents of the receiver // and kv2. If any key exists in both slices, the value from kv2 is used. The @@ -184,15 +184,15 @@ out: // EnvKV generates key/value pairs from a configuration object's struct tags // -// Parameters: +// # Parameters // // - cfg: A configuration object whose struct fields are processed for env tags // -// Return values: +// # Return Values // // - m: A KVSlice containing key/value pairs derived from the config's env tags // -// Expected behaviour: +// # Expected Behaviour: // // Processes each field of the config object, extracting values tagged with // "env" and converting them to strings. Skips fields without an "env" tag. @@ -227,13 +227,13 @@ func EnvKV(cfg any) (m KVSlice) { // PrintEnv outputs sorted environment key/value pairs from a configuration object // to the provided writer // -// Parameters: +// # Parameters // // - cfg: Pointer to the configuration object containing env tags // // - printer: Destination for the output, typically an io.Writer implementation // -// Expected behaviour: +// # Expected Behaviour: // // Outputs each environment variable derived from the config's struct tags in // sorted order, formatted as "key=value\n" to the specified writer @@ -249,13 +249,13 @@ func PrintEnv(cfg *C, printer io.Writer) { // variable configuration, and details about .env file handling to the provided // writer // -// Parameters: +// # Parameters // // - cfg: Configuration object containing app name and config directory path // // - printer: Output destination for the help text // -// Expected behaviour: +// # Expected Behaviour: // // Prints application name and version followed by environment variable // configuration details, explains .env file behaviour including automatic diff --git a/pkg/app/main.go b/pkg/app/main.go index 22fe357..d2168b7 100644 --- a/pkg/app/main.go +++ b/pkg/app/main.go @@ -28,11 +28,11 @@ type Relay struct { // Name returns the name of the application represented by this relay. // -// Return Values: +// # Return Values // // - string: the name of the application. // -// Expected behaviour: +// # Expected behaviour // // This function simply returns the AppName field from the configuration. func (r *Relay) Name() string { return r.C.AppName } @@ -42,11 +42,11 @@ func (r *Relay) Storage() store.I { return r.Store } // Init initializes and sets up the relay for Nostr events. // -// Return Values: +// #Return Values // // - err: an error if any issues occurred during initialization. // -// Expected behaviour: +// #Expected behaviour // // This function is responsible for setting up the relay, configuring it, // and initializing the necessary components to handle Nostr events. @@ -57,25 +57,30 @@ func (r *Relay) Init() (err error) { // AcceptEvent checks an event and determines whether the event should be // accepted and if the client has the authority to submit it. // -// Parameters: +// # Parameters // // - c - a context.T for signalling if the task has been canceled. +// // - evt - an *event.E that is being evaluated. +// // - hr - an *http.Request containing the information about the current // connection. +// // - origin - the address of the client. +// // - authedPubkey - the public key, if authed, of the client for this // connection. // -// Return Values: +// # Return Values // // - accept - returns true if the event is accepted. -// - notice - if it is not accepted, -// a message in the form of `machine-readable-prefix: reason for -// error/blocked/rate-limited/etc` +// +// - notice - if it is not accepted, a message in the form of +// `machine-readable-prefix: reason for error/blocked/rate-limited/etc` +// // - afterSave - a closure to run after the event has been stored. // -// Expected behaviour: +// # Expected behaviour // // This function checks whether the client has permission to store the event, // and if they don't, returns false and some kind of error message. If they do, @@ -91,7 +96,7 @@ func (r *Relay) AcceptEvent( // AcceptFilter checks if a filter is allowed based on authentication status and // relay policies // -// Parameters: +// # Parameters // // - c: Context for task cancellation. // @@ -101,7 +106,7 @@ func (r *Relay) AcceptEvent( // // - authedPubkey: Public key of authenticated client, if applicable. // -// Return values: +// # Return values // // - allowed: The filter if permitted; may be modified during processing. // @@ -110,7 +115,7 @@ func (r *Relay) AcceptEvent( // - modified: Boolean indicating whether the filter was altered during // evaluation. // -// Expected behaviour: +// # Expected behaviour // // The method evaluates whether the provided filter should be allowed based on // authentication status and relay-specific rules. If permitted, returns the @@ -128,7 +133,7 @@ func (r *Relay) AcceptFilter( // AcceptReq evaluates whether the provided filters are allowed based on // authentication status and relay policies for an incoming HTTP request. // -// Parameters: +// # Parameters // // - c: Context for task cancellation. // @@ -140,7 +145,7 @@ func (r *Relay) AcceptFilter( // // - authedPubkey: Public key of authenticated client, if applicable. // -// Return values: +// # Return Values // // - allowed: The filters if permitted; may be modified during processing. // @@ -149,7 +154,7 @@ func (r *Relay) AcceptFilter( // - modified: Boolean indicating whether the filters were altered during // evaluation. // -// Expected behaviour: +// # Expected Behaviour: // // The method evaluates whether the provided filters should be allowed based on // authentication status and relay-specific rules. If permitted, returns the diff --git a/pkg/app/relay/accept-event.go b/pkg/app/relay/accept-event.go index 8d1f267..a676e13 100644 --- a/pkg/app/relay/accept-event.go +++ b/pkg/app/relay/accept-event.go @@ -10,21 +10,27 @@ import ( // AcceptEvent determines whether an incoming event should be accepted for // processing based on authentication requirements. // -// Parameters: +// # Parameters // // - c: the context of the request +// // - ev: pointer to the event structure +// // - hr: HTTP request related to the event (if any) +// // - authedPubkey: public key of the authenticated user (if any) +// // - remote: remote address from where the event was received // -// Return Values: +// # Return Values // // - accept: boolean indicating whether the event should be accepted +// // - notice: string providing a message or error notice +// // - afterSave: function to execute after saving the event (if applicable) // -// Expected Behaviour: +// # Expected Behaviour: // // - If authentication is required and no public key is provided, reject the // event. diff --git a/pkg/app/relay/accept-req.go b/pkg/app/relay/accept-req.go index f94a74a..e03545a 100644 --- a/pkg/app/relay/accept-req.go +++ b/pkg/app/relay/accept-req.go @@ -10,20 +10,28 @@ import ( // AcceptReq determines whether a request should be accepted based on // authentication and public readability settings. // -// Parameters: +// # Parameters +// // - c: context for the request handling +// // - hr: HTTP request received +// // - f: filters to apply +// // - authedPubkey: authenticated public key (if any) +// // - remote: remote address of the request // -// Return Values: +// # Return Values +// // - allowed: filters that are allowed after processing +// // - accept: boolean indicating whether the request should be accepted +// // - modified: boolean indicating if the request has been modified during // processing // -// Expected Behaviour: +// # Expected Behaviour: // // - If authentication is required and there's no authenticated public key, // reject the request. diff --git a/pkg/app/relay/addEvent.go b/pkg/app/relay/addEvent.go index 5c283c6..823ad67 100644 --- a/pkg/app/relay/addEvent.go +++ b/pkg/app/relay/addEvent.go @@ -16,24 +16,37 @@ import ( // AddEvent processes an incoming event, saves it if valid, and delivers it to // subscribers. // -// Parameters: +// # Parameters +// // - c: context for request handling +// // - rl: relay interface +// // - ev: the event to be added +// // - hr: HTTP request related to the event (if any) +// // - origin: origin of the event (if any) +// // - authedPubkey: public key of the authenticated user (if any) // -// Return Values: +// # Return Values +// // - accepted: true if the event was successfully processed, false otherwise +// // - message: additional information or error message related to the // processing // -// Expected Behaviour: +// # Expected Behaviour: +// // - Validates the incoming event. +// // - Saves the event using the Publish method if it is not ephemeral. +// // - Handles duplicate events by returning an appropriate error message. +// // - Delivers the event to subscribers via the listeners' Deliver method. +// // - Returns a boolean indicating whether the event was accepted and any // relevant message. func (s *Server) AddEvent( diff --git a/pkg/app/relay/auth.go b/pkg/app/relay/auth.go index e31ebcc..2f9efca 100644 --- a/pkg/app/relay/auth.go +++ b/pkg/app/relay/auth.go @@ -15,15 +15,15 @@ import ( // wss) based on headers like X-Forwarded-Host, X-Forwarded-Proto, and the host // itself. // -// Parameters: +// # Parameters // // - req: A pointer to an http.Request object representing the incoming request. // -// Return Values: +// # Return Values // // - st: A string representing the constructed service URL. // -// Expected Behaviour: +// # Expected Behaviour: // // - Checks if authentication is required. // diff --git a/pkg/app/relay/handleRelayinfo.go b/pkg/app/relay/handleRelayinfo.go index 4e30605..06b09f5 100644 --- a/pkg/app/relay/handleRelayinfo.go +++ b/pkg/app/relay/handleRelayinfo.go @@ -11,11 +11,25 @@ import ( "sort" ) -func (s *Server) handleRelayInfo(w http.ResponseWriter, r *http.Request) { +// HandleRelayInfo generates and returns a relay information document in JSON +// format based on the server's configuration and supported NIPs. +// +// # Parameters +// +// - w: HTTP response writer used to send the generated document. +// +// - r: HTTP request object containing incoming client request data. +// +// # Expected Behaviour +// +// The function constructs a relay information document using either the +// Informer interface implementation or predefined server configuration. It +// returns this document as a JSON response to the client. +func (s *Server) HandleRelayInfo(w http.ResponseWriter, r *http.Request) { r.Header.Set("Content-Type", "application/json") log.I.Ln("handling relay information document") var info *relayinfo.T - if informationer, ok := s.relay.(relay.Informationer); ok { + if informationer, ok := s.relay.(relay.Informer); ok { info = informationer.GetNIP11InformationDocument() } else { supportedNIPs := relayinfo.GetList( diff --git a/pkg/app/relay/helpers/helpers.go b/pkg/app/relay/helpers/helpers.go index b825eed..f2e2fab 100644 --- a/pkg/app/relay/helpers/helpers.go +++ b/pkg/app/relay/helpers/helpers.go @@ -8,19 +8,19 @@ import ( // GenerateDescription generates a detailed description containing the provided // text and an optional list of scopes. // -// Parameters: +// # Parameters // // - text: A string representing the base description. // // - scopes: A slice of strings indicating scopes to be included in the // description. // -// Return values: +// # Return Values // // - A string combining the base description and a formatted list of // scopes, if provided. // -// Expected behavior: +// # Expected behaviour // // The function appends a formatted list of scopes to the base description if // any scopes are provided. If no scopes are provided, it returns the base @@ -40,20 +40,20 @@ func GenerateDescription(text string, scopes []string) string { // GetRemoteFromReq retrieves the originating IP address of the client from // an HTTP request, considering standard and non-standard proxy headers. // -// Parameters: +// # Parameters // // - r: The HTTP request object containing details of the client and // routing information. // -// Return values: +// # Return Values // // - rr: A string value representing the IP address of the originating // remote client. // -// Expected behavior: +// # Expected behaviour // // The function first checks for the standardized "Forwarded" header (RFC 7239) -// to identify the original client IP. If that's not available, it falls back to +// to identify the original client IP. If that isn't available, it falls back to // the "X-Forwarded-For" header. If both headers are absent, it defaults to // using the request's RemoteAddr. // @@ -83,7 +83,6 @@ func GetRemoteFromReq(r *http.Request) (rr string) { } } } - // If the Forwarded header is not available or doesn't contain "for" // parameter, fall back to X-Forwarded-For rem := r.Header.Get("X-Forwarded-For") diff --git a/pkg/app/relay/options/options.go b/pkg/app/relay/options/options.go index 4ad53a1..2d93c5d 100644 --- a/pkg/app/relay/options/options.go +++ b/pkg/app/relay/options/options.go @@ -1,7 +1,7 @@ // Package options provides some option configurations for the relay. // // None of this package is actually in use, and the skip event function has not -// been implemented. In theory this could be used for something but it currently +// been implemented. In theory, this could be used for something but it currently // isn't. package options diff --git a/pkg/app/relay/server.go b/pkg/app/relay/server.go index bb24940..2716c5a 100644 --- a/pkg/app/relay/server.go +++ b/pkg/app/relay/server.go @@ -72,7 +72,7 @@ type ServerParams struct { // - Initializes storage with the provided database path. // // - Configures the server's options using the default settings and applies any -// optional settings provided. +// optional settings provided. // // - Sets up a ServeMux for handling HTTP requests. // @@ -121,7 +121,7 @@ func NewServer(sp *ServerParams, opts ...options.O) (s *Server, err error) { // // - For WebSocket upgrades, calls handleWebsocket method. // -// - If "Accept" header is "application/nostr+json", calls handleRelayInfo +// - If "Accept" header is "application/nostr+json", calls HandleRelayInfo // method. // // - Logs the HTTP request details for non-standard requests. @@ -136,7 +136,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } if r.Header.Get("Accept") == "application/nostr+json" { - s.handleRelayInfo(w, r) + s.HandleRelayInfo(w, r) return } } diff --git a/pkg/app/resources.go b/pkg/app/resources.go index 2a03de2..fd825be 100644 --- a/pkg/app/resources.go +++ b/pkg/app/resources.go @@ -8,6 +8,19 @@ import ( "time" ) +// MonitorResources periodically logs resource usage metrics such as the number +// of active goroutines and CGO calls at 15-minute intervals, and exits when the +// provided context signals cancellation. +// +// # Parameters +// +// - c: Context used to control the lifecycle of the resource monitoring process. +// +// # Expected behaviour +// +// The function runs indefinitely, logging metrics every 15 minutes until the +// context is cancelled. Upon cancellation, it logs a shutdown message and exits +// gracefully without returning any values. func MonitorResources(c context.T) { tick := time.NewTicker(time.Minute * 15) log.I.Ln("running process", os.Args[0], os.Getpid()) diff --git a/pkg/interfaces/relay/interface.go b/pkg/interfaces/relay/interface.go index e6830d5..00ad5ae 100644 --- a/pkg/interfaces/relay/interface.go +++ b/pkg/interfaces/relay/interface.go @@ -11,7 +11,7 @@ import ( // I is the main interface for implementing a nostr relay. type I interface { // Name is used as the "name" field in NIP-11 and as a prefix in default - // S logging. For other NIP-11 fields, see [Informationer]. + // S logging. For other NIP-11 fields, see [Informer]. Name() string // Init is called at the very beginning by [S.Start], allowing a realy // to initialize its internal resources. @@ -20,10 +20,10 @@ type I interface { Storage() store.I } -// Informationer is called to compose NIP-11 response to an HTTP request +// Informer is called to compose NIP-11 response to an HTTP request // with application/nostr+json mime type. // See also [I.Name]. -type Informationer interface { +type Informer interface { GetNIP11InformationDocument() *relayinfo.T } diff --git a/pkg/protocol/socketapi/handleClose.go b/pkg/protocol/socketapi/handleClose.go index 4c161cf..bdf4760 100644 --- a/pkg/protocol/socketapi/handleClose.go +++ b/pkg/protocol/socketapi/handleClose.go @@ -10,14 +10,14 @@ import ( // HandleClose processes a CLOSE envelope, intended to cancel a specific // subscription, and notifies the server to handle the cancellation. // -// Parameters: +// # Parameters // // - req: A byte slice containing the raw CLOSE envelope data to process. // // - srv: The server instance responsible for managing subscription // operations, such as cancellation. // -// Return values: +// # Return Values // // - note: A byte slice containing an error message if issues occur during // processing; otherwise, an empty slice. diff --git a/pkg/protocol/socketapi/handleEvent.go b/pkg/protocol/socketapi/handleEvent.go index 68ba5bf..307f58d 100644 --- a/pkg/protocol/socketapi/handleEvent.go +++ b/pkg/protocol/socketapi/handleEvent.go @@ -22,7 +22,7 @@ import ( // checks its signature, and performs necessary actions such as storing, // deleting, or responding to the event. // -// Parameters: +// # Parameters // // - c: a context object used for managing deadlines, cancellation signals, // and other request-scoped values. @@ -33,7 +33,7 @@ import ( // - srv: an interface representing the server context, providing access to // storage and other server-level utilities. // -// Return values: +// # Return Values // // - msg: a byte slice representing the response message generated by the // method. The content depends on the processing outcome. diff --git a/pkg/protocol/socketapi/handleMessage.go b/pkg/protocol/socketapi/handleMessage.go index e613067..67b09d4 100644 --- a/pkg/protocol/socketapi/handleMessage.go +++ b/pkg/protocol/socketapi/handleMessage.go @@ -16,7 +16,7 @@ import ( // delegates handling to the appropriate method based on the message's envelope // type. // -// Parameters: +// # Parameters // // - msg: A byte slice representing the raw message to be processed. // diff --git a/pkg/protocol/socketapi/handleReq.go b/pkg/protocol/socketapi/handleReq.go index 64cf72f..15f08ba 100644 --- a/pkg/protocol/socketapi/handleReq.go +++ b/pkg/protocol/socketapi/handleReq.go @@ -20,7 +20,7 @@ import ( // and interacts with the server storage and subscription mechanisms to query // events or manage subscriptions. // -// Parameters: +// # Parameters // // - c: A context object used for managing deadlines, cancellation signals, // and other request-scoped values. @@ -30,7 +30,7 @@ import ( // - srv: An interface representing the server, providing access to storage // and subscription management. // -// Return values: +// # Return Values // // - r: A byte slice containing the response or error message generated // during processing. diff --git a/pkg/protocol/socketapi/pinger.go b/pkg/protocol/socketapi/pinger.go index 004c37e..a7506ac 100644 --- a/pkg/protocol/socketapi/pinger.go +++ b/pkg/protocol/socketapi/pinger.go @@ -13,7 +13,7 @@ import ( // alive and responsive. It terminates the connection if pings fail or the // context is canceled. // -// Parameters: +// # Parameters // // - ctx: A context object used to monitor cancellation signals and // manage termination of the method execution. diff --git a/pkg/protocol/socketapi/socketapi.go b/pkg/protocol/socketapi/socketapi.go index 632a320..f702bbf 100644 --- a/pkg/protocol/socketapi/socketapi.go +++ b/pkg/protocol/socketapi/socketapi.go @@ -37,7 +37,7 @@ type A struct { // managing the WebSocket connection, and delegating received messages for // processing. // -// Parameters: +// # Parameters // // - w: The HTTP response writer used to manage the connection upgrade. // diff --git a/pkg/utils/apputil/apputil.go b/pkg/utils/apputil/apputil.go index f43a79d..51225d2 100644 --- a/pkg/utils/apputil/apputil.go +++ b/pkg/utils/apputil/apputil.go @@ -11,7 +11,7 @@ import ( // necessary directories if they don't exist. It ensures that all parent // directories in the path are created with the appropriate permissions. // -// Parameters: +// # Parameters // // - fileName: The full path to the file for which directories need to be // created. @@ -37,7 +37,7 @@ func EnsureDir(fileName string) (merr error) { // FileExists reports whether the named file or directory exists. // -// Parameters: +// # Parameters // // - filePath: The full path to the file or directory to check. //