深入 Elasticsearch(18):用 Docker 或 Podman 搭建 HTTP 实验集群
每次练习先从 Elastic 官方版本目录解析最新稳定版本,再拉取对应的官方镜像,启动一个只在本机开放 HTTP 的三节点集群。一次实验固定一个版本,结果同时记录镜像标识和服务器版本;下一次用新的空环境验证升级后的行为。 本章为前面的原理章节提供运行环境,直接复用《08 补充:查询与检索》的 mapping、三份文档和查询附件。它不另写一套字段示例,也不把“请求返回 200”当成“命中结果正确”。 这是无认证、无 TLS 的本地实验环境,不是生产部署模板。 只有第一个节点的 HTTP 端口映射到 127.0.0.1:19200,节点间的 transport 通信留在容器网络中。默认关闭机器学习,插件、模型与安全实验需要另行准备。 先定义镜像、节点、集群与实验数据 镜像是启动程序和依赖的发行包。tag 是版本名称,image ID 与 digest 用于记录实际拉取的内容;容器是运行中的一个 Elasticsearch 节点。三个节点加入相同的 cluster,并通过容器网络发现彼此。 HTTP 的 9200 端口供 curl、Postman 或应用提交 REST 请求。tran...
Kotlin 23:文件读写失败后旧任务还在吗
任务输入之前只存在于 双模块工程的内存中。现在要从文件读入任务行,再写一份文本文件:读到文件末尾、提前遇到结束标记、读取过程中抛异常,三条路径会不会把 Reader 留着?已经有一份旧文件时,新文件只写了一半便失败,旧内容还能否读到? 这里使用冻结的 Kotlin/JVM 2.2.21、JDK 21、Gradle 8.14,输入只包含合成任务 ID 与文本,不处理用户传来的文件路径或外部命令。Kotlin stdlib use API提供带关闭的作用域;JDK 21 Files、Process 和 ProcessBuilder是文件及子进程边界的依据。下文的关闭次数、退出码与文件内容来自本次运行,不是文档对所有文件系统的承诺。 从 Reader 提前返回时谁来关流 文件格式有意保持简单:每行是 id<TAB>text,整行 #stop 表示后续输入不再导入。readTaskRows(reader: Reader) 先调用 reader.buffered().use { ... };遇到 EOF 返回行列表,遇到 #stop 用 return@us...
Python E05:Web 框架如何承接已有业务入口
34 的 JSON 行服务用 {"op":"submit"} 表示一次提交。换成 HTTP 时,POST /tasks 可以返回 201,但状态码只表示服务器接受了任务,绝不等于统计已经执行。新增的麻烦是客户端可能在任务执行中断开;如果请求处理器把任务丢到无人管理的后台,query 就可能在连接早已消失后仍看到它悄悄提交结果。 这次选 Starlette 0.46.2 作可移除适配层,由 Uvicorn 0.34.2 提供回环 HTTP 服务,HTTPX 0.28.1 负责实际客户端请求。它们和传递依赖装在仓库外的 /private/tmp/python-language-completion/optional,主线 wheel 仍保持零运行依赖。不会把 HTTP 请求体解释成 Python 模块名、任意函数或文件路径。 映射只发生在边界 experiments/E05_asgi.py 接受的路径固定为 POST /tasks、GET /tasks/{id}、POST /tasks/{id...
Python E04:换解释器后哪些结论失效
tasklab 的 cpu_work 在 CPython 上每次约要十几毫秒;把同一个文件交给 PyPy,五次调用里的第一次数量级也可能与后四次不同。仅凭这个差异不能说“换解释器就能加速任务应用”:先要确定项目能否导入、四个操作的结果是否相同,再谈被计时的究竟是哪段代码。 本篇沿用 39 的可安装 wheel 和 36 的测量边界。当前 completion 基线是 CPython 3.12.3、free-threaded CPython 3.13.9,以及 macOS arm64 上的 PyPy 8.0.0(Python 3.12.14,官方归档)。解释器版本、项目要求的 Python 版本和 wheel 的安装位置分别记录;本次没有用 PyPy 3.9 代跑当前项目,因为 requires-python = ">=3.12" 已把它排除在验收范围之外。 先看能否完成合同 PyPy 8.0.0 的当前环境记录在 examples/python-language/evidence/completion/acceptance/pypy-environme...
Kotlin 22:测试通过为何仍可能漏掉契约
clean test 退出 0 很有用,但它回答的是“已经写下的断言是否通过”,不是“任务系统所有规则都已验证”。一个测试只调用 submitValidated,却不检查返回的 Rejected、旧记录是否被改写,照样可以是绿色。另一方面,少写一个密封状态分支的代码连测试进程都无法启动。让后一种反例进入正常 src/test 会把整个构建变红,正常业务回归也无法完成。 沿用 21 的双模块工程::domain 存放 TaskState 与 TaskStore,根模块运行 Kotlin/Java 的 JUnit 测试。冻结 Kotlin 插件/stdlib 2.2.21、Gradle 8.14、JDK 21,没有新增测试库。Kotlin 的 JUnit JVM 测试指南、kotlin.test API 和 Gradle 测试指南用于确认测试入口;下述诊断和结果均是固定工程本次运行的原始输出。 业务规则要具体到哪一组输入和结果 12 的状态模型只有 `Queued → Running`、从 `Queued` 直接取消、`Running` 后成功/失败/取消等允许的路径;已终止状态不...
Kotlin 21:构建脚本里的 Kotlin 和应用 Kotlin 是同一个吗
在已经能跑通 Java 消费者测试 的工程中执行 ./gradlew --version,看到的 Kotlin 是 2.0.21;build.gradle.kts 中的 Kotlin Gradle Plugin 和应用的 stdlib 却是 2.2.21。两个数字出现在同一条构建链上,分别约束什么?如果要把任务状态和存储放进领域模块,哪一处依赖决定应用能否找到这些类? 这里仍用冻结的 Gradle Wrapper 8.14、Ubuntu OpenJDK 21.0.12.1、Kotlin Gradle Plugin/stdlib 2.2.21,语言与 API 版本为 2.2,目标字节码为 JVM 21。完整版本、Wrapper 校验和已固定的上游源码 tag SHA 在下载工程的 VERSIONS.md;下文只描述这一组合已经运行的结果,不用官方 Kotlin Gradle 配置文档中的滚动兼容表冒充本机运行证据。 一个工程里为什么能有三处 Kotlin 版本 ./gradlew --version 的 Kotlin 2.0.21 是 Gradle 8.14 自带的构建逻辑运行环...
Kotlin 20:Java 调用 Kotlin 时默认参数去哪了
Kotlin 可以写 describe("task-1"),让第二个参数使用默认值;Java 调用同一个声明,却不一定能少传参数。反方向的 19已经补过 class、interface、implements、static、泛型擦除和 checked exception 的最小 Java 前置;这次将边界倒过来:用真实 src/test/java 消费者编译调用 Kotlin 方法,比较 @JvmOverloads、@JvmStatic、@Throws 到底改变了 Java 所见的哪一部分契约。 冻结组合仍是 Kotlin Gradle Plugin/stdlib 2.2.21、JDK 21、Gradle 8.14;本篇只生成单个同步 facade,不发布公共库。官方 Java 调 Kotlin 文档提供注解和属性映射规则;下文的具体生成方法、Java 编译诊断和异常结果来自本次 javap、javac 和 JUnit,不能拿滚动文档代替当前产物。 Java 消费者只认识类文件里实际存在的方法、字段访问器和 throws 签名。Kotlin 的 object、属...
Kotlin 19:Java 返回值怎样越过空安全边界
Kotlin 的非空变量在本地代码里不允许直接赋 null,但 Java 方法返回一个没有空注解的 String,实际却可以返回 null。如果 Kotlin 直接对这个返回值取 .length,编译器会放行,运行时仍可能抛 NullPointerException。已有的 05 空安全实验处理的是 Kotlin 自己声明的可空字段;本篇把同一任务系统接上一小段 Java 输入适配器,记录 Java 返回值越界后的实际行为,以及在哪里将它变回明确的 Kotlin 类型。 本章沿用 Kotlin Gradle Plugin/stdlib 2.2.21、Gradle Wrapper 8.14 和 JDK 21;未新增三方依赖。规则出处是 Kotlin 官方 Java 空安全与 platform type、SAM 转换。具体值、异常和调用时序以本仓库 19 的 Kotlin/Java 混合编译及测试日志为准。Java 类的空注解、线程调度或真实网络在本篇都不存在。 Java 前置:类、接口、擦除和 checked exception Java 的 class 承载字段、构造器、实例方...
Kotlin 18:任务注解为什么不会自动校验
给任务草稿标上 @TaskCategory("draft"),运行时可以读到这份元数据;再标一个仅供源码阶段使用的提示,运行时却读不到。更容易误会的是:类上写着“需要校验”,是否意味着创建一个正文全为空白的草稿会被自动拦住?本篇沿用 17 的 TaskDraft,比较注解目标、保留期和实际调用 Class.getAnnotation 的结果,明确哪些逻辑仍需要普通函数执行。 实验组合是 Kotlin/JVM 2.2.21、JDK 21、Gradle Wrapper 8.14。出处定位在 Kotlin 注解文档与 反射文档;本章只用 JDK 的 Class.getAnnotation 和 Kotlin 标准库的 ::class.java,没有添加 kotlin-reflect 依赖,也没有编译器插件或扫描容器。实验中的类型、编译器诊断和字节码都可在 18 证据目录核对。 注解贴在哪里,留下多久 两个注解都只能标在类上,但保留期不同: 1234567891011@Target(AnnotationTarget.CLASS)@Retention(Annotatio...
Kotlin 17:DSL 嵌套作用域怎样限制误写
任务草稿有 ID、正文和若干标签。普通函数写成 makeTaskDraft(id, text, labels),参数一目了然;改成 taskDraft { ... label { ... } } 后,在最内层 label 块里写 text = "overwritten" 到底会修改标签,还是悄悄修改外层任务正文?此前 14 的作用域函数已经说明接收者与返回值可能不是同一回事,这里让两个接收者同时进入作用域,再用编译反例确认 @DslMarker 的保护范围。 本文实验仍在 Kotlin/JVM 2.2.21、JDK 21、Gradle 8.14 上运行。语法依据是 官方类型安全构造器的作用域控制 和 带接收者函数字面量;具体允许或拒绝哪条语句,以冻结编译器的原始输出为准。 普通构造函数已经解决什么 本章的产物只是值 TaskDraft(id: TaskId, text: String, labels: List<String>)。makeTaskDraft 在构造前检查正文非空、每个标签 trim 后非空,...










