Merge pull request #1392 from gavin-ts/custom-timeout

configure timeout with D2_TIMEOUT
This commit is contained in:
gavin-ts 2023-06-14 17:20:42 -07:00 committed by GitHub
commit c4ba2074de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 11 deletions

View file

@ -1,5 +1,7 @@
#### Features 🚀 #### Features 🚀
- Configure timeout value with D2_TIMEOUT env var. [#1392](https://github.com/terrastruct/d2/pull/1392)
#### Improvements 🧹 #### Improvements 🧹
- Display version on CLI help invocation [#1400](https://github.com/terrastruct/d2/pull/1400) - Display version on CLI help invocation [#1400](https://github.com/terrastruct/d2/pull/1400)

View file

@ -103,30 +103,41 @@ Set the diagram layout engine to the passed string. For a list of available opti
.Ar layout .Ar layout
.Ns . .Ns .
.It Fl b , -bundle Ar true .It Fl b , -bundle Ar true
Bundle all assets and layers into the output svg. Bundle all assets and layers into the output svg
.Ns .
.It Fl -force-appendix Ar false .It Fl -force-appendix Ar false
An appendix for tooltips and links is added to PNG exports since they are not interactive. Setting this to true adds an appendix to SVG exports as well An appendix for tooltips and links is added to PNG exports since they are not interactive. Setting this to true adds an appendix to SVG exports as well
.Ns . .Ns .
.It Fl d , -debug .It Fl d , -debug
Print debug logs. Print debug logs
.Ns .
.It Fl -img-cache Ar true .It Fl -img-cache Ar true
In watch mode, images used in icons are cached for subsequent compilations. This should be disabled if images might change In watch mode, images used in icons are cached for subsequent compilations. This should be disabled if images might change
.Ns . .Ns .
.It Fl -timeout Ar 120
The maximum number of seconds that D2 runs for before timing out and exiting. When rendering a large diagram, it is recommended to increase this value
.Ns .
.It Fl h , -help .It Fl h , -help
Print usage information and exit. Print usage information and exit
.Ns .
.It Fl v , -version .It Fl v , -version
Print version information and exit. Print version information and exit
.Ns .
.El .El
.Sh SUBCOMMANDS .Sh SUBCOMMANDS
.Bl -tag -width Fl .Bl -tag -width Fl
.It Ar layout .It Ar layout
Lists available layout engine options with short help. Lists available layout engine options with short help
.Ns .
.It Ar layout Op Ar name .It Ar layout Op Ar name
Display long help for a particular layout engine, including its configuration options. Display long help for a particular layout engine, including its configuration options
.Ns .
.It Ar themes .It Ar themes
Lists available themes. Lists available themes
.Ns .
.It Ar fmt Ar file.d2 ... .It Ar fmt Ar file.d2 ...
Format all passed files. Format all passed files
.Ns .
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr d2plugin-tala 1 .Xr d2plugin-tala 1

View file

@ -37,6 +37,7 @@ import (
"oss.terrastruct.com/d2/lib/png" "oss.terrastruct.com/d2/lib/png"
"oss.terrastruct.com/d2/lib/pptx" "oss.terrastruct.com/d2/lib/pptx"
"oss.terrastruct.com/d2/lib/textmeasure" "oss.terrastruct.com/d2/lib/textmeasure"
timelib "oss.terrastruct.com/d2/lib/time"
"oss.terrastruct.com/d2/lib/version" "oss.terrastruct.com/d2/lib/version"
"oss.terrastruct.com/d2/lib/xgif" "oss.terrastruct.com/d2/lib/xgif"
@ -88,6 +89,11 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
if err != nil { if err != nil {
return err return err
} }
timeoutFlag, err := ms.Opts.Int64("D2_TIMEOUT", "timeout", "", 120, "the maximum number of seconds that D2 runs for before timing out and exiting. When rendering a large diagram, it is recommended to increase this value")
if err != nil {
return err
}
versionFlag, err := ms.Opts.Bool("", "version", "v", false, "get the version") versionFlag, err := ms.Opts.Bool("", "version", "v", false, "get the version")
if err != nil { if err != nil {
return err return err
@ -160,6 +166,9 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
if *browserFlag != "" { if *browserFlag != "" {
ms.Env.Setenv("BROWSER", *browserFlag) ms.Env.Setenv("BROWSER", *browserFlag)
} }
if timeoutFlag != nil {
os.Setenv("D2_TIMEOUT", fmt.Sprintf("%d", *timeoutFlag))
}
var inputPath string var inputPath string
var outputPath string var outputPath string
@ -298,7 +307,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
return w.run() return w.run()
} }
ctx, cancel := context.WithTimeout(ctx, time.Minute*2) ctx, cancel := timelib.WithTimeout(ctx, time.Minute*2)
defer cancel() defer cancel()
_, written, err := compile(ctx, ms, plugin, renderOpts, fontFamily, *animateIntervalFlag, inputPath, outputPath, *bundleFlag, *forceAppendixFlag, pw.Page) _, written, err := compile(ctx, ms, plugin, renderOpts, fontFamily, *animateIntervalFlag, inputPath, outputPath, *bundleFlag, *forceAppendixFlag, pw.Page)

View file

@ -15,6 +15,7 @@ import (
"oss.terrastruct.com/util-go/xmain" "oss.terrastruct.com/util-go/xmain"
"oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2graph"
timelib "oss.terrastruct.com/d2/lib/time"
) )
// execPlugin uses the binary at pathname with the plugin protocol to implement // execPlugin uses the binary at pathname with the plugin protocol to implement
@ -147,7 +148,7 @@ func (p *execPlugin) Info(ctx context.Context) (_ *PluginInfo, err error) {
} }
func (p *execPlugin) Layout(ctx context.Context, g *d2graph.Graph) error { func (p *execPlugin) Layout(ctx context.Context, g *d2graph.Graph) error {
ctx, cancel := context.WithTimeout(ctx, time.Minute) ctx, cancel := timelib.WithTimeout(ctx, time.Minute*2)
defer cancel() defer cancel()
graphBytes, err := d2graph.SerializeGraph(g) graphBytes, err := d2graph.SerializeGraph(g)

View file

@ -16,6 +16,7 @@ import (
"time" "time"
"oss.terrastruct.com/d2/lib/log" "oss.terrastruct.com/d2/lib/log"
timelib "oss.terrastruct.com/d2/lib/time"
) )
//go:embed template.html //go:embed template.html
@ -69,8 +70,10 @@ func main() {
if !*skipTests { if !*skipTests {
ctx := log.Stderr(context.Background()) ctx := log.Stderr(context.Background())
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
ctx, cancel := timelib.WithTimeout(ctx, 2*time.Minute)
defer cancel() defer cancel()
// don't want to pass empty args to CommandContext // don't want to pass empty args to CommandContext
args := []string{"test", testDir, testMatchString} args := []string{"test", testDir, testMatchString}
if cpuProfileStr != "" { if cpuProfileStr != "" {

11
lib/env/env.go vendored
View file

@ -2,6 +2,7 @@ package env
import ( import (
"os" "os"
"strconv"
) )
func Test() bool { func Test() bool {
@ -25,3 +26,13 @@ func DevOnly() bool {
func SkipGraphDiffTests() bool { func SkipGraphDiffTests() bool {
return os.Getenv("SKIP_GRAPH_DIFF_TESTS") != "" return os.Getenv("SKIP_GRAPH_DIFF_TESTS") != ""
} }
func Timeout() (int, bool) {
if s := os.Getenv("D2_TIMEOUT"); s != "" {
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
return int(i), true
}
}
return -1, false
}

26
lib/time/time.go Normal file
View file

@ -0,0 +1,26 @@
package time
import (
"context"
"time"
"oss.terrastruct.com/d2/lib/env"
)
func HumanDate(t time.Time) string {
local := t.Local()
return local.Format(time.RFC822)
}
// WithTimeout returns context.WithTimeout(ctx, timeout) but timeout is overridden with D2_TIMEOUT if set
func WithTimeout(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
t := timeout
if seconds, has := env.Timeout(); has {
t = time.Duration(seconds) * time.Second
}
if t <= 0 {
return ctx, func() {}
}
return context.WithTimeout(ctx, t)
}