Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.go text eol=lf
54 changes: 30 additions & 24 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,51 @@
<!-- 标题写做成了什么,不写路线图编号。读者第一次看这个仓库时,「第 6b 步」没有意义;路线图编号写在正文里。 -->
<!-- State the result in the title. Do not put a ROADMAP number in the title. -->

## 改了什么,为什么
## What Changed and Why

<!-- 先写行为或问题,再写为什么需要改。不要逐个罗列文件。 -->
<!-- State the behavior or problem first. Then state why the change is needed. -->

## 关联 issue
## Related Issue

<!-- 有对应 issue 写 Fixes #N 自动关闭;没有就删掉这一栏。 -->
<!-- Use "Fixes #N" when this change closes an issue. Otherwise, remove this
section. -->

## Spec 依据
## Specification

<!-- 链接 docs/ 或 design/,并写对应 ROADMAP 步骤号;不在路线图上说明理由。spec 和实装有差距时,写明文内「差距」小节。 -->
<!-- Link to docs/ or design/ and state the ROADMAP step. Explain an unplanned
change. Add a Gap section when the implementation differs from the
specification. -->

## 破坏性变更与迁移
## Breaking Changes and Migration

<!-- 没有写「无」。有则说明什么不兼容、影响谁、如何迁移。 -->
<!-- Write "None" or state what is incompatible, who it affects, and how to
migrate. -->

## 面向用户的变更
## User-Visible Change

<!-- 没有用户可见变更写 NONE;否则写一句可直接进入 release notes 的说明。 -->
<!-- Write "NONE" or add one sentence that can go into the release notes. -->
```release-note

```

## 验证
## Verification

<!-- 写实际执行的命令、环境和结果。手工验证写步骤;未验证说明原因。性能变更给出基线和结果。 -->
<!-- State each command, environment, and result. Give steps for a manual
check. State why a check was not run. Give the baseline and result for a
performance change. -->

## 变异测试
## Mutation Test

<!--
新增或改动了测试就填这里:故意改坏了哪行生产代码,哪个测试红了,红的理由是什么。
理由不对的变异(比如因为「类型没注册」而失败)不算杀死。
纯文档改动填 N/A
For a new or changed test, state the production change that you made to cause
a failure. State which test failed and why. A failure for an unrelated reason
does not kill the mutation. Use "N/A" for a documentation-only change.
-->

## 必须检查
## Required Checks

- [ ] `make ci` 在本地绿
- [ ] 没有新旧测试并存
- [ ] 生产代码里没有 `time.Now()`
- [ ] 没有用 `time.Sleep` 做同步
- [ ] 没有用 mutex 做跨调用等待
- [ ] 有 spec 支撑;spec 和实装的差距已在文内说明
- [ ] `make ci` passes locally.
- [ ] Old and new tests do not test the same contract.
- [ ] Production code does not call `time.Now()`.
- [ ] Tests do not use `time.Sleep` for synchronization.
- [ ] Code does not use a mutex to wait across Calls.
- [ ] A specification supports the change. It states each implementation gap.
74 changes: 64 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
strategy:
matrix:
go-version: ["1.25.x", "stable"]
Expand All @@ -20,23 +20,77 @@ jobs:
with:
go-version: ${{ matrix.go-version }}
cache: true
- name: Install staticcheck
run: |
go install honnef.co/go/tools/cmd/staticcheck@v0.6.1
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
- name: Verify platform
run: go run ./internal/platformcheck -os linux -arch amd64
- name: Run CI checks
run: make ci
- name: Run govulncheck
if: matrix.go-version == 'stable'
run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
run: go tool govulncheck ./...
macos:
runs-on: macos-15
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.x"
cache: true
- name: Verify platform
run: go run ./internal/platformcheck -os darwin -arch arm64
- name: Run default tests
run: go run ./internal/testcheck ./...
- name: Run simulation tests
run: go run ./internal/testcheck -tags sim -run '^TestSim' ./sim/...
- name: Run generator tests
run: go run ./internal/testcheck -tags gen ./cmd/gorgen/...
- name: Check generated test package
run: go tool gorgen -pkg ./cmd/gorgen/testfixture/endtoend/domain -check
- name: Check generated example package
run: go tool gorgen -pkg ./examples/shadow/domain -check
- name: Run transport network tests
run: go run ./internal/testcheck -tags net ./transport/...
- name: Run example network tests
run: go run ./internal/testcheck -tags net ./examples/shadow/...
windows:
runs-on: windows-2025
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.x"
cache: true
- name: Verify platform
run: go run ./internal/platformcheck -os windows -arch amd64
- name: Run default tests
run: go run ./internal/testcheck ./...
- name: Run simulation tests
run: go run ./internal/testcheck -tags sim -run '^TestSim' ./sim/...
- name: Run generator tests
run: go run ./internal/testcheck -tags gen ./cmd/gorgen/...
- name: Check generated test package
run: go tool gorgen -pkg ./cmd/gorgen/testfixture/endtoend/domain -check
- name: Check generated example package
run: go tool gorgen -pkg ./examples/shadow/domain -check
- name: Run transport network tests
run: go run ./internal/testcheck -tags net ./transport/...
- name: Run example network tests
run: go run ./internal/testcheck -tags net ./examples/shadow/...
ci:
if: ${{ always() }}
needs: test
runs-on: ubuntu-latest
needs: [test, macos, windows]
runs-on: ubuntu-24.04
steps:
- name: Verify matrix result
- name: Verify required jobs
run: |
echo "matrix result: ${{ needs.test.result }}"
if [ "${{ needs.test.result }}" != "success" ]; then
echo "macOS result: ${{ needs.macos.result }}"
echo "Windows result: ${{ needs.windows.result }}"
if [ "${{ needs.test.result }}" != "success" ] || \
[ "${{ needs.macos.result }}" != "success" ] || \
[ "${{ needs.windows.result }}" != "success" ]; then
exit 1
fi
31 changes: 29 additions & 2 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ The stable identity of one Grain. It contains a GrainType and a GrainKey.
_Avoid_: identity, address, instance ID, object ID

**GrainType**:
The kind of Grain. Grains with different GrainTypes do not share a GrainId.
The stable Application name for one kind of Grain. Grains with different
GrainTypes do not share a GrainId.
_Avoid_: class, model, category

**GrainKey**:
Expand All @@ -26,6 +27,11 @@ _Avoid_: ID, name, identifier
A typed value that names a Grain without creating it.
_Avoid_: proxy, handle, stub, pointer

**Grain Context**:
Runtime data for one Activation. The Application uses it to get State, Grain
References, Grain Timers, Reminders, and lifecycle controls.
_Avoid_: Binder, service provider, runtime handle

**Call**:
A request to run one method on a Grain through a Grain Reference.
_Avoid_: message, invocation, packet
Expand All @@ -37,6 +43,7 @@ _Avoid_: header, context value, request property

**Call Filter**:
Shared policy that runs before or after a Call.
Call Filters are deferred until after 0.1.0.
_Avoid_: interceptor, middleware

## Runtime model
Expand All @@ -56,11 +63,16 @@ The end of an Activation. Deactivation does not delete a Grain's GrainId or
State.
_Avoid_: destroy, delete, terminate

**Deactivate on Idle**:
A request from a Grain to end its Activation after the current Call. The next
Call uses a new Activation.
_Avoid_: delete Grain, stop Grain, destroy instance

**Lifecycle**:
The path from Activation to Deactivation for one Grain.
_Avoid_: object lifetime, process lifetime

## State and reminders
## State and time

**State**:
The current data owned by a Grain. State describes the Grain now.
Expand All @@ -79,6 +91,21 @@ A future Call that the Grain Runtime remembers for a Grain. A Reminder can
happen once or repeat on a period.
_Avoid_: timer, wake-up, scheduled task, job

**Invalid Reminder**:
A persisted Reminder whose GrainType or method is not installed. The Grain
Runtime cannot make its Call.
_Avoid_: bad job, dead letter, broken timer

**Terminal Result**:
The result that removes one unchanged Invalid Reminder. Later scans cannot
return it. A new Set creates a new Reminder setting.
_Avoid_: tombstone, dead letter

**Grain Timer**:
An Activation-local callback that a Grain schedules. The Grain Runtime does
not save it and discards it when the Activation ends.
_Avoid_: Reminder, job, scheduler

## Call results

**Conflict**:
Expand Down
23 changes: 0 additions & 23 deletions FINDINGS.md

This file was deleted.

72 changes: 52 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,31 +1,67 @@
.PHONY: test sim gen lint net fmt fmt-check ci tidy bench
.PHONY: test sim gen generated-check lint net fuzz resource release-command-check external external-tagged tidy-check fmt fmt-check race ci tidy bench

# Keep release evidence in the specified order, including with make -j.
.NOTPARALLEL:

# Caller-provided Make variables must not replace release test commands.
FUZZ_TIME ?= 10s

test:
go test ./...
go run ./internal/testcheck ./...

# 性能基线单独运行,不进默认 test;GOR_BENCH_DIR 可指定真盘目录
# Benchmarks run separately. GOR_BENCH_DIR can select a real-disk directory.
bench:
go test . -run '^$$' -bench . -benchmem -count=1

# 模拟测试跑得慢,单独一条 target,不进默认 test
# Simulation tests run separately from the default test target.
sim:
go test -tags sim -run TestSim ./sim/...
go run ./internal/testcheck -tags sim -run '^TestSim' ./sim/...

# 生成器的端到端测试要起 go list 子进程,同样不进默认 test
# Generator integration tests start Go subprocesses and run separately.
gen:
go test -tags gen ./cmd/gorgen/...
go run ./internal/testcheck -tags gen ./cmd/gorgen/...
go tool gorgen -pkg ./cmd/gorgen/testfixture/endtoend/domain -check
go tool gorgen -pkg ./examples/shadow/domain -check

generated-check:
go tool gorgen -pkg ./cmd/gorgen/testfixture/endtoend/domain -check
go tool gorgen -pkg ./examples/shadow/domain -check

# TCP 的传输测试单独运行,不进默认 test
# Real TCP tests run separately from the default test target.
net:
go test -tags net ./transport/...
go test -tags net ./examples/shadow/...
go run ./internal/testcheck -tags net ./transport/...
go run ./internal/testcheck -tags net ./examples/shadow/...

fuzz:
go run ./internal/testcheck ./transport -run '^$$' -fuzz '^FuzzReadFrame$$' -fuzztime=$(FUZZ_TIME)
go run ./internal/testcheck . -run '^$$' -fuzz '^FuzzDecodeRequestContext$$' -fuzztime=$(FUZZ_TIME)
go run ./internal/testcheck ./internal/codegen -run '^$$' -fuzz '^FuzzParseGrainMarker$$' -fuzztime=$(FUZZ_TIME)

resource:
go run ./internal/testcheck ./internal/runtime -run '^TestRuntime_ActivationChurnReleasesOwnedResources$$' -count=1
go run ./internal/testcheck ./internal/timer -run '^TestPoller_LargeBacklogKeepsPagesAndWorkersBounded$$' -count=1

release-command-check:
go run ./internal/testcheck -tags release ./internal/testcheck -run '^TestMakefile_ReleaseCommandsKeepTestcheck$$' -count=1

# External release proof uses empty Go caches and separate operating system processes.
external: release-command-check
go run ./internal/testcheck -tags release -run '^TestQuickStartHTTPProcess$$' ./examples/shadow/cmd/shadow
go run ./internal/testcheck -tags release -run '^TestExternalModule(Configuration|RestartProof|UpgradeProof)$$' ./examples/shadow/cmd/conformance

# Published release proof resolves the fixed tag without a local replacement.
external-tagged: release-command-check
go run ./internal/testcheck -tags release -run '^TestExternalModule(Configuration|RestartProof|UpgradeProof)$$' ./examples/shadow/cmd/conformance -args -external-tagged

tidy-check:
go mod tidy -diff

lint:
go run ./internal/constraintcheck
go vet ./...
staticcheck ./...
go tool staticcheck ./...
go vet -tags sim ./sim/...
staticcheck -tags sim ./sim/...
go tool staticcheck -tags sim ./sim/...

fmt:
gofmt -l -w .
Expand All @@ -37,14 +73,10 @@ fmt-check:
exit 1; \
fi

ci:
$(MAKE) fmt-check
$(MAKE) lint
$(MAKE) test
go test -count=1 -race ./...
$(MAKE) sim
$(MAKE) gen
$(MAKE) net
race:
go run ./internal/testcheck -count=1 -race ./...

ci: fmt-check tidy-check lint release-command-check test race sim gen net resource fuzz

tidy:
go mod tidy
Loading
Loading