Skip to content

Commit 5561c48

Browse files
authored
Admin server port (#99)
Replaced hard-coded port `3001` with a configurable `AdminServerPort` field in `Config`. Updated `dbos.go` to use the provided port (defaulting to 3001) and adjusted tests to use a custom port (`38081`). ✅ All `TestAdminServer` cases now pass.
1 parent 1c802bb commit 5561c48

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

dbos/admin_server_test.go

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestAdminServer(t *testing.T) {
3636

3737
// Verify admin server is not running
3838
client := &http.Client{Timeout: 1 * time.Second}
39-
_, err = client.Get(fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_HEALTHCHECK_PATTERN, "GET /")))
39+
_, err = client.Get(fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_HEALTHCHECK_PATTERN, "GET /")))
4040
require.Error(t, err, "Expected request to fail when admin server is not started")
4141

4242
// Verify the DBOS executor doesn't have an admin server instance
@@ -51,9 +51,10 @@ func TestAdminServer(t *testing.T) {
5151
resetTestDatabase(t, databaseURL)
5252
// Launch DBOS with admin server once for all endpoint tests
5353
ctx, err := NewDBOSContext(Config{
54-
DatabaseURL: databaseURL,
55-
AppName: "test-app",
56-
AdminServer: true,
54+
DatabaseURL: databaseURL,
55+
AppName: "test-app",
56+
AdminServer: true,
57+
AdminServerPort: _DEFAULT_ADMIN_SERVER_PORT,
5758
})
5859
require.NoError(t, err)
5960

@@ -92,13 +93,13 @@ func TestAdminServer(t *testing.T) {
9293
{
9394
name: "Health endpoint responds correctly",
9495
method: "GET",
95-
endpoint: fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_HEALTHCHECK_PATTERN, "GET /")),
96+
endpoint: fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_HEALTHCHECK_PATTERN, "GET /")),
9697
expectedStatus: http.StatusOK,
9798
},
9899
{
99100
name: "Recovery endpoint responds correctly with valid JSON",
100101
method: "POST",
101-
endpoint: fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_WORKFLOW_RECOVERY_PATTERN, "POST /")),
102+
endpoint: fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_WORKFLOW_RECOVERY_PATTERN, "POST /")),
102103
body: bytes.NewBuffer(mustMarshal([]string{"executor1", "executor2"})),
103104
contentType: "application/json",
104105
expectedStatus: http.StatusOK,
@@ -112,15 +113,15 @@ func TestAdminServer(t *testing.T) {
112113
{
113114
name: "Recovery endpoint rejects invalid JSON",
114115
method: "POST",
115-
endpoint: fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_WORKFLOW_RECOVERY_PATTERN, "POST /")),
116+
endpoint: fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_WORKFLOW_RECOVERY_PATTERN, "POST /")),
116117
body: strings.NewReader(`{"invalid": json}`),
117118
contentType: "application/json",
118119
expectedStatus: http.StatusBadRequest,
119120
},
120121
{
121122
name: "Queue metadata endpoint responds correctly",
122123
method: "GET",
123-
endpoint: fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_WORKFLOW_QUEUES_METADATA_PATTERN, "GET /")),
124+
endpoint: fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_WORKFLOW_QUEUES_METADATA_PATTERN, "GET /")),
124125
expectedStatus: http.StatusOK,
125126
validateResp: func(t *testing.T, resp *http.Response) {
126127
var queueMetadata []WorkflowQueue
@@ -146,7 +147,7 @@ func TestAdminServer(t *testing.T) {
146147
{
147148
name: "Workflows endpoint accepts all filters without error",
148149
method: "POST",
149-
endpoint: fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_WORKFLOWS_PATTERN, "POST /")),
150+
endpoint: fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_WORKFLOWS_PATTERN, "POST /")),
150151
body: bytes.NewBuffer(mustMarshal(map[string]any{
151152
"workflow_uuids": []string{"test-id-1", "test-id-2"},
152153
"authenticated_user": "test-user",
@@ -177,7 +178,7 @@ func TestAdminServer(t *testing.T) {
177178
{
178179
name: "Get single workflow returns 404 for non-existent workflow",
179180
method: "GET",
180-
endpoint: "http://localhost:3001/workflow/non-existent-workflow-id",
181+
endpoint: fmt.Sprintf("http://localhost:%d/workflow/non-existent-workflow-id", _DEFAULT_ADMIN_SERVER_PORT),
181182
expectedStatus: http.StatusNotFound,
182183
},
183184
}
@@ -214,9 +215,10 @@ func TestAdminServer(t *testing.T) {
214215
t.Run("List workflows input/output values", func(t *testing.T) {
215216
resetTestDatabase(t, databaseURL)
216217
ctx, err := NewDBOSContext(Config{
217-
DatabaseURL: databaseURL,
218-
AppName: "test-app",
219-
AdminServer: true,
218+
DatabaseURL: databaseURL,
219+
AppName: "test-app",
220+
AdminServer: true,
221+
AdminServerPort: _DEFAULT_ADMIN_SERVER_PORT,
220222
})
221223
require.NoError(t, err)
222224

@@ -258,7 +260,7 @@ func TestAdminServer(t *testing.T) {
258260
time.Sleep(100 * time.Millisecond)
259261

260262
client := &http.Client{Timeout: 5 * time.Second}
261-
endpoint := fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_WORKFLOWS_PATTERN, "POST /"))
263+
endpoint := fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_WORKFLOWS_PATTERN, "POST /"))
262264

263265
// Create workflows with different input/output types
264266
// 1. Integer workflow
@@ -360,9 +362,10 @@ func TestAdminServer(t *testing.T) {
360362
t.Run("List endpoints time filtering", func(t *testing.T) {
361363
resetTestDatabase(t, databaseURL)
362364
ctx, err := NewDBOSContext(Config{
363-
DatabaseURL: databaseURL,
364-
AppName: "test-app",
365-
AdminServer: true,
365+
DatabaseURL: databaseURL,
366+
AppName: "test-app",
367+
AdminServer: true,
368+
AdminServerPort: _DEFAULT_ADMIN_SERVER_PORT,
366369
})
367370
require.NoError(t, err)
368371

@@ -382,7 +385,7 @@ func TestAdminServer(t *testing.T) {
382385
}()
383386

384387
client := &http.Client{Timeout: 5 * time.Second}
385-
endpoint := fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_WORKFLOWS_PATTERN, "POST /"))
388+
endpoint := fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_WORKFLOWS_PATTERN, "POST /"))
386389

387390
// Create first workflow
388391
handle1, err := RunWorkflow(ctx, testWorkflow, "workflow1")
@@ -533,9 +536,10 @@ func TestAdminServer(t *testing.T) {
533536
t.Run("ListQueuedWorkflows", func(t *testing.T) {
534537
resetTestDatabase(t, databaseURL)
535538
ctx, err := NewDBOSContext(Config{
536-
DatabaseURL: databaseURL,
537-
AppName: "test-app",
538-
AdminServer: true,
539+
DatabaseURL: databaseURL,
540+
AppName: "test-app",
541+
AdminServer: true,
542+
AdminServerPort: _DEFAULT_ADMIN_SERVER_PORT,
539543
})
540544
require.NoError(t, err)
541545

@@ -570,7 +574,7 @@ func TestAdminServer(t *testing.T) {
570574
}()
571575

572576
client := &http.Client{Timeout: 5 * time.Second}
573-
endpoint := fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_QUEUED_WORKFLOWS_PATTERN, "POST /"))
577+
endpoint := fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_QUEUED_WORKFLOWS_PATTERN, "POST /"))
574578

575579
/// Create a workflow that will not block the queue
576580
h1, err := RunWorkflow(ctx, regularWorkflow, "regular", WithQueue(queue.Name))
@@ -718,9 +722,10 @@ func TestAdminServer(t *testing.T) {
718722
t.Run("TestDeactivate", func(t *testing.T) {
719723
resetTestDatabase(t, databaseURL)
720724
ctx, err := NewDBOSContext(Config{
721-
DatabaseURL: databaseURL,
722-
AppName: "test-app",
723-
AdminServer: true,
725+
DatabaseURL: databaseURL,
726+
AppName: "test-app",
727+
AdminServer: true,
728+
AdminServerPort: _DEFAULT_ADMIN_SERVER_PORT,
724729
})
725730
require.NoError(t, err)
726731

@@ -754,7 +759,7 @@ func TestAdminServer(t *testing.T) {
754759
}, 3*time.Second, 100*time.Millisecond, "Expected at least 2 scheduled workflow executions")
755760

756761
// Call deactivate endpoint
757-
endpoint := fmt.Sprintf("http://localhost:3001/%s", strings.TrimPrefix(_DEACTIVATE_PATTERN, "GET /"))
762+
endpoint := fmt.Sprintf("http://localhost:%d/%s", _DEFAULT_ADMIN_SERVER_PORT, strings.TrimPrefix(_DEACTIVATE_PATTERN, "GET /"))
758763
req, err := http.NewRequest("GET", endpoint, nil)
759764
require.NoError(t, err, "Failed to create deactivate request")
760765

dbos/dbos.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type Config struct {
3636
AppName string // Application name for identification (required)
3737
Logger *slog.Logger // Custom logger instance (defaults to a new slog logger)
3838
AdminServer bool // Enable Transact admin HTTP server (disabled by default)
39+
AdminServerPort int // Port for the admin HTTP server (default: 3001)
3940
ConductorURL string // DBOS conductor service URL (optional)
4041
ConductorAPIKey string // DBOS conductor API key (optional)
4142
ApplicationVersion string // Application version (optional, overridden by DBOS__APPVERSION env var)
@@ -51,12 +52,16 @@ func processConfig(inputConfig *Config) (*Config, error) {
5152
if len(inputConfig.AppName) == 0 {
5253
return nil, fmt.Errorf("missing required config field: appName")
5354
}
55+
if inputConfig.AdminServerPort == 0 {
56+
inputConfig.AdminServerPort = _DEFAULT_ADMIN_SERVER_PORT
57+
}
5458

5559
dbosConfig := &Config{
5660
DatabaseURL: inputConfig.DatabaseURL,
5761
AppName: inputConfig.AppName,
5862
Logger: inputConfig.Logger,
5963
AdminServer: inputConfig.AdminServer,
64+
AdminServerPort: inputConfig.AdminServerPort,
6065
ConductorURL: inputConfig.ConductorURL,
6166
ConductorAPIKey: inputConfig.ConductorAPIKey,
6267
ApplicationVersion: inputConfig.ApplicationVersion,
@@ -372,13 +377,13 @@ func (c *dbosContext) Launch() error {
372377

373378
// Start the admin server if configured
374379
if c.config.AdminServer {
375-
adminServer := newAdminServer(c, _DEFAULT_ADMIN_SERVER_PORT)
380+
adminServer := newAdminServer(c, c.config.AdminServerPort)
376381
err := adminServer.Start()
377382
if err != nil {
378383
c.logger.Error("Failed to start admin server", "error", err)
379384
return newInitializationError(fmt.Sprintf("failed to start admin server: %v", err))
380385
}
381-
c.logger.Info("Admin server started", "port", _DEFAULT_ADMIN_SERVER_PORT)
386+
c.logger.Info("Admin server started", "port", c.config.AdminServerPort)
382387
c.adminServer = adminServer
383388
}
384389

0 commit comments

Comments
 (0)