# Concurrency Verified

✅ - A checkmark means "this has been tested, and will run concurrently".\
❔ - The questionmark means "it hasn't been tested, safety unknown"\
❌ - The red "X" means "this has been tested, and it will *not* work concurrently".

Concurrency in this context is about gathering zone data, as seen during the preview stage when fetching current data for all zones.

#### Here's how to perform a test:

1. Build dnscontrol with the -race flag: go build -race (this makes a special binary)
2. Run this special binary: `dnscontrol preview` with a configuration that lists at least 4 domains using the provider in question. More domains is better.
3. The special binary runs much slower (1/10th the speed) because it is doing a lot of checking.

If it reports problems, the error message will indicate where the problem is. It might not be 100% accurate, but it will be in the right area.

#### Development guidance

Loosely, each Provider has a top-level struct named `{providername}Provider`; if this state is just some simple data-types initialized once before processing starts, and then only read, then the provider is likely to be concurrency-safe.

If this contains state which is updated (eg, caches) then the provider is probably not concurrency-safe unless every routine accessing it is protected by appropriate primitives.

Eg, URLs and auth credentials are fine. An account ID determined on the first query? That probably needs to be protected, even if every fetch returns the same data.

The `-race` build is a helpful hint but is not a guarantee.

**Multiple Providers**

Most simple use-cases likely use just one copy of a given provider, managing zones in an account. But there can be multiple *distinct* copies, each for different accounts. Someone might use this while migrating accounts, for instance. You might have two fields in `creds.json` both with a `TYPE` of your provider.

The uses of the provider objects should never create copies; each is created by a constructor, but thereafter is a singleton per constructed provider. Thus it is safe to have synchronization objects inside the provider struct.

See, for example, the `dnsimple` provider, where there is a `sync.Once` *per object*, not at a global level, so that the `.accountID` can be fetched just once per configured provider. Because `sync.Once` contains a reference to `sync.noCopy`, the `go vet` command will catch attempts to copy that object, and so will catch attempts to copy the containing `dnsimpleProvider` object.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dnscontrol.org/~/revisions/Uy3v06HuP9Hvf4EPf9c7/advanced-features/concurrency-verified.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
