Skip to content

Commit aacc733

Browse files
authored
Merge pull request #79 from nitrictech/feat/api-listing
Add API listing for config as code
2 parents 8b4f1b1 + d53d566 commit aacc733

File tree

8 files changed

+266
-34
lines changed

8 files changed

+266
-34
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ require (
2525
github.com/moby/buildkit v0.9.3 // indirect
2626
github.com/moby/moby v20.10.12+incompatible
2727
github.com/nitrictech/boxygen v0.0.1-rc.7.0.20211212231606-62c668408f91
28-
github.com/nitrictech/nitric v0.13.0-rc.11
28+
github.com/nitrictech/nitric v0.13.0-rc.17
2929
github.com/pkg/errors v0.9.1
3030
github.com/pterm/pterm v0.12.34
3131
github.com/pulumi/pulumi-aws/sdk/v4 v4.33.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,8 +1287,8 @@ github.com/nishanths/predeclared v0.2.1 h1:1TXtjmy4f3YCFjTxRd8zcFHOmoUir+gp0ESzj
12871287
github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE=
12881288
github.com/nitrictech/boxygen v0.0.1-rc.7.0.20211212231606-62c668408f91 h1:gtZZJc7l5pML1eRsqyXe0U7NdQxSa7u/cbyEvnGLBpc=
12891289
github.com/nitrictech/boxygen v0.0.1-rc.7.0.20211212231606-62c668408f91/go.mod h1:2XXi1xEwqitH4/gus1bHyG/IQe8WOniK+pybGTz2y/Y=
1290-
github.com/nitrictech/nitric v0.13.0-rc.11 h1:nn4j71Wk32KV0j3zN5y/S8eCpVYjeR/E3PYOkFgt1lY=
1291-
github.com/nitrictech/nitric v0.13.0-rc.11/go.mod h1:XC6DG1/NrMc59Jzq/1h6SLn6L4foSS67pCqyTpauT3o=
1290+
github.com/nitrictech/nitric v0.13.0-rc.17 h1:Pv6aGNP/+kHNVt87QfT06bqpbKIy2s3SYcqYXDIRKE4=
1291+
github.com/nitrictech/nitric v0.13.0-rc.17/go.mod h1:XC6DG1/NrMc59Jzq/1h6SLn6L4foSS67pCqyTpauT3o=
12921292
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
12931293
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
12941294
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=

pkg/cmd/run/root.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ import (
2020
"fmt"
2121
"os"
2222
"os/signal"
23+
"sync"
2324
"syscall"
2425
"time"
2526

2627
"github.com/pkg/errors"
28+
"github.com/pterm/pterm"
2729
"github.com/spf13/cobra"
2830

2931
"github.com/nitrictech/cli/pkg/build"
@@ -85,11 +87,13 @@ nitric run -s ../projectX/ "functions/*.ts"`,
8587
ls := run.NewLocalServices(s.Name, s.Dir)
8688
memerr := make(chan error)
8789

90+
pool := run.NewRunProcessPool()
91+
8892
startLocalServices := tasklet.Runner{
8993
StartMsg: "Starting Local Services",
9094
Runner: func(progress output.Progress) error {
9195
go func(errch chan error) {
92-
errch <- ls.Start()
96+
errch <- ls.Start(pool)
9397
}(memerr)
9498

9599
for {
@@ -137,25 +141,34 @@ nitric run -s ../projectX/ "functions/*.ts"`,
137141
}
138142
tasklet.MustRun(startFunctions, tasklet.Opts{Signal: term})
139143

140-
fmt.Println("Local running, use ctrl-C to stop")
141-
142-
type apiendpoint struct {
143-
Api string `yaml:"api"`
144-
Endpoint string `yaml:"endpoint"`
145-
}
146-
apis := []apiendpoint{}
147-
148-
for a := range s.ApiDocs {
149-
apis = append(apis, apiendpoint{Api: a, Endpoint: fmt.Sprintf("http://127.0.0.1:9001/apis/%s", a)})
150-
}
144+
pterm.DefaultBasicText.Println("Local running, use ctrl-C to stop")
145+
146+
stackState := run.NewStackState()
147+
148+
area, _ := pterm.DefaultArea.Start()
149+
lck := sync.Mutex{}
150+
// React to worker pool state and update services table
151+
pool.Listen(func(we run.WorkerEvent) {
152+
lck.Lock()
153+
defer lck.Unlock()
154+
stackState.UpdateFromWorkerEvent(we)
155+
area.Update(
156+
stackState.ApiTable(9001),
157+
"\n\n",
158+
stackState.TopicTable(9001),
159+
"\n\n",
160+
stackState.SchedulesTable(9001),
161+
)
162+
})
151163

152-
if len(apis) == 0 {
153-
// if we have a nitric.yaml then ApiDocs will be empty
154-
for a := range s.Apis {
155-
apis = append(apis, apiendpoint{Api: a, Endpoint: fmt.Sprintf("http://127.0.0.1:9001/apis/%s", a)})
156-
}
157-
}
158-
output.Print(apis)
164+
// TODO: revisit nitric.yaml support for this output
165+
// if len(apis) == 0 {
166+
// // if we have a nitric.yaml then ApiDocs will be empty
167+
// for a := range s.Apis {
168+
// apis[a] = fmt.Sprintf("http://127.0.0.1:9001/apis/%s", a)
169+
// }
170+
// }
171+
// output.Print(apis)
159172

160173
select {
161174
case membraneError := <-memerr:
@@ -170,6 +183,7 @@ nitric run -s ../projectX/ "functions/*.ts"`,
170183
}
171184
}
172185

186+
_ = area.Stop()
173187
_ = logger.Stop()
174188
// Stop the membrane
175189
cobra.CheckErr(ls.Stop())

pkg/run/pool.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright Nitric Pty Ltd.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at:
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
package run
18+
19+
import "github.com/nitrictech/nitric/pkg/worker"
20+
21+
type WorkerEventType string
22+
23+
const (
24+
WorkerEventType_Add WorkerEventType = "add"
25+
WorkerEventType_Remove WorkerEventType = "remove"
26+
)
27+
28+
type WorkerEvent struct {
29+
Type WorkerEventType
30+
Worker worker.Worker
31+
}
32+
33+
type WorkerListener = func(WorkerEvent)
34+
35+
type RunProcessPool struct {
36+
worker.WorkerPool
37+
listeners []WorkerListener
38+
}
39+
40+
func (r *RunProcessPool) notifyListeners(evt WorkerEvent) {
41+
for _, l := range r.listeners {
42+
l(evt)
43+
}
44+
}
45+
46+
func (r *RunProcessPool) AddWorker(w worker.Worker) error {
47+
if err := r.WorkerPool.AddWorker(w); err != nil {
48+
return err
49+
}
50+
// notify listener of successfully added worker
51+
r.notifyListeners(WorkerEvent{
52+
Type: WorkerEventType_Add,
53+
Worker: w,
54+
})
55+
return nil
56+
}
57+
58+
func (r *RunProcessPool) RemoveWorker(w worker.Worker) error {
59+
if err := r.WorkerPool.RemoveWorker(w); err != nil {
60+
return err
61+
}
62+
// notify listener of successfully removed worker
63+
r.notifyListeners(WorkerEvent{
64+
Type: WorkerEventType_Remove,
65+
Worker: w,
66+
})
67+
return nil
68+
}
69+
70+
func (r *RunProcessPool) Listen(l WorkerListener) {
71+
r.listeners = append(r.listeners, l)
72+
}
73+
74+
func NewRunProcessPool() *RunProcessPool {
75+
return &RunProcessPool{
76+
listeners: make([]WorkerListener, 0),
77+
WorkerPool: worker.NewProcessPool(&worker.ProcessPoolOptions{
78+
MinWorkers: 0,
79+
MaxWorkers: 100,
80+
}),
81+
}
82+
}

pkg/run/run.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434
)
3535

3636
type LocalServices interface {
37-
Start() error
37+
Start(pool worker.WorkerPool) error
3838
Stop() error
3939
Running() bool
4040
Status() *LocalServicesStatus
@@ -85,7 +85,7 @@ func (l *localServices) Status() *LocalServicesStatus {
8585
return l.status
8686
}
8787

88-
func (l *localServices) Start() error {
88+
func (l *localServices) Start(pool worker.WorkerPool) error {
8989
var err error
9090
l.mio, err = NewMinio(l.status.RunDir, "minio")
9191
if err != nil {
@@ -129,14 +129,6 @@ func (l *localServices) Start() error {
129129
return err
130130
}
131131

132-
// Create a new Worker Pool
133-
// TODO: We may want to override GetWorker on the default ProcessPool
134-
// For now we'll use the default and expand from there
135-
pool := worker.NewProcessPool(&worker.ProcessPoolOptions{
136-
MinWorkers: 0,
137-
MaxWorkers: 100,
138-
})
139-
140132
ev, err := NewEvents(pool)
141133
if err != nil {
142134
return err

pkg/run/stack.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright Nitric Pty Ltd.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at:
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
package run
18+
19+
import (
20+
"fmt"
21+
"strings"
22+
23+
"github.com/pterm/pterm"
24+
25+
"github.com/nitrictech/nitric/pkg/worker"
26+
)
27+
28+
type RunStackState struct {
29+
apis map[string]int
30+
subs map[string]int
31+
schedules map[string]int
32+
}
33+
34+
func (r *RunStackState) UpdateFromWorkerEvent(evt WorkerEvent) {
35+
if evt.Type == WorkerEventType_Add {
36+
switch evt.Worker.(type) {
37+
case *worker.RouteWorker:
38+
w := evt.Worker.(*worker.RouteWorker)
39+
40+
if _, ok := r.apis[w.Api()]; !ok {
41+
r.apis[w.Api()] = 1
42+
} else {
43+
r.apis[w.Api()] = r.apis[w.Api()] + 1
44+
}
45+
case *worker.SubscriptionWorker:
46+
w := evt.Worker.(*worker.SubscriptionWorker)
47+
48+
if _, ok := r.subs[w.Topic()]; !ok {
49+
r.subs[w.Topic()] = 1
50+
} else {
51+
r.subs[w.Topic()] = r.subs[w.Topic()] + 1
52+
}
53+
case *worker.ScheduleWorker:
54+
w := evt.Worker.(*worker.ScheduleWorker)
55+
56+
if _, ok := r.schedules[w.Key()]; !ok {
57+
r.schedules[w.Key()] = 1
58+
} else {
59+
r.schedules[w.Key()] = r.schedules[w.Key()] + 1
60+
}
61+
}
62+
} else if evt.Type == WorkerEventType_Remove {
63+
switch evt.Worker.(type) {
64+
case *worker.RouteWorker:
65+
w := evt.Worker.(*worker.RouteWorker)
66+
67+
r.apis[w.Api()] = r.apis[w.Api()] - 1
68+
69+
if r.apis[w.Api()] <= 0 {
70+
// Remove the key if the reference count is 0 or less
71+
delete(r.apis, w.Api())
72+
}
73+
case *worker.SubscriptionWorker:
74+
w := evt.Worker.(*worker.SubscriptionWorker)
75+
76+
r.subs[w.Topic()] = r.subs[w.Topic()] - 1
77+
78+
if r.subs[w.Topic()] <= 0 {
79+
// Remove the key if the reference count is 0 or less
80+
delete(r.subs, w.Topic())
81+
}
82+
case *worker.ScheduleWorker:
83+
w := evt.Worker.(*worker.ScheduleWorker)
84+
85+
r.schedules[w.Key()] = r.schedules[w.Key()] - 1
86+
87+
if r.schedules[w.Key()] <= 0 {
88+
// Remove the key if the reference count is 0 or less
89+
delete(r.schedules, w.Key())
90+
}
91+
}
92+
}
93+
}
94+
95+
func (r *RunStackState) ApiTable(port int) string {
96+
tableData := pterm.TableData{{"Api", "Endpoint"}}
97+
98+
for k := range r.apis {
99+
tableData = append(tableData, []string{
100+
k, fmt.Sprintf("http://localhost:%d/apis/%s", port, k),
101+
})
102+
}
103+
104+
str, _ := pterm.DefaultTable.WithHasHeader().WithData(tableData).Srender()
105+
106+
return str
107+
}
108+
109+
func (r *RunStackState) TopicTable(port int) string {
110+
tableData := pterm.TableData{{"Topic", "Endpoint"}}
111+
112+
for k := range r.subs {
113+
tableData = append(tableData, []string{
114+
k, fmt.Sprintf("http://localhost:%d/topics/%s", port, k),
115+
})
116+
}
117+
118+
str, _ := pterm.DefaultTable.WithHasHeader().WithData(tableData).Srender()
119+
120+
return str
121+
}
122+
123+
func (r *RunStackState) SchedulesTable(port int) string {
124+
tableData := pterm.TableData{{"Schedule", "Endpoint"}}
125+
126+
for k := range r.schedules {
127+
nKey := strings.ToLower(strings.ReplaceAll(k, " ", "-"))
128+
tableData = append(tableData, []string{
129+
k, fmt.Sprintf("http://localhost:%d/topics/%s", port, nKey),
130+
})
131+
}
132+
133+
str, _ := pterm.DefaultTable.WithHasHeader().WithData(tableData).Srender()
134+
135+
return str
136+
}
137+
138+
func NewStackState() *RunStackState {
139+
return &RunStackState{
140+
apis: map[string]int{},
141+
subs: map[string]int{},
142+
schedules: map[string]int{},
143+
}
144+
}

pkg/stack/function_helpers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestFunctionVersionString(t *testing.T) {
2929
}{
3030
{
3131
name: "from embed",
32-
want: "v0.13.0-rc.11",
32+
want: "v0.13.0-rc.17",
3333
},
3434
{
3535
name: "from function",

pkg/stack/membraneversion.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.13.0-rc.11
1+
v0.13.0-rc.17

0 commit comments

Comments
 (0)