url path: /topic/delete 入口函数:doDeleteTopic->DeleteExistingTopic 一、根据topicName获取Topic对象指针,注意这里只需要用读锁控制并发,对应topic不存在直接报错并返回 二、topic.Delete(),需要注意的是在关闭topic之前先删除channel和topic,这样做的目的是不会有任何消息未被处理,同时所有写入操作都将出错,并且不会创建新的topic来强制排序 内部调用了exit(deleted bool)函数,入参为true,逻辑如下 1、设置exitFlag,从0到1,如果旧值不是0,则已经存在删除topic任务,直接退出 2、因为deleted为true,则会调用t.ctx.nsqd.Notify(t),最终会发送消息到lookupd,metadata落盘 3、close(t.exitChan),关闭exitChan,会触发messagePump函数中的goto exit操作,会停止消息接收 4、然后处理channel,遍历channelMap,从map中删除对应channelName(这个删除map感觉没必要遍历删除,直接删除整个map效率更高) 5、channel.Delete,内部调用了func (c *Channel) exit(deleted bool) error,deleted为true, 逻辑和topic的Exit类似,区别在于 1)需要关闭连接到该channel的client 2)Empty: InFlightCount置为0,并调用tryUpdateReadyState函数推动func (p *protocolV2) messagePump(client *clientV2, startedChan chan bool)for循环进入下一个周期,然后给emptyChan通道赋值(会触发ioLoop中的deleteAllFiles函数, skipToNextRWFile删除读写的文件,并清空对应字段值,也把metadata文件删除,紧接着把count计数器置为0,防止出发sync操作) 3) c.backend.Delete():关闭exitChan,会触发关闭ioLoop操作,同时接收exitSyncChan返回,确保ioLoop被关闭,然后再把读写两个文件句柄关闭 6、t.Empty,删除topic相关的文件,逻辑和channel的Empty相同 7、t.backend.Delete(),同5.3) 接下来的逻辑都类似了,清理文件操作,看一下DiskQueue的逻辑即可 三、在topicMap中删除对应topicName的对象