在写单元测试的时候,有时候需要伪造时间,例如一个token的有效期30天,但是我的单元测试不可能等30天或其他什么的,所以,,,可以使用freezegun这个库去伪造时间,更多不介绍了,官网,很详细的使用说明.
在写单元测试的时候,有时候需要伪造时间,例如一个token的有效期30天,但是我的单元测试不可能等30天或其他什么的,所以,,,可以使用freezegun这个库去伪造时间,更多不介绍了,官网,很详细的使用说明.
假设有这样的场景, 某实体在具体条目上, 其属性是不定的, 或者其属性是充分稀疏的:
id | name | attr_0 | attr_1 | attr_2 | … | attr_n |
---|---|---|---|---|---|---|
1 | foo | 1 | abc | 33 | … | any |
这种情况下, 把属性看成是单独的实体, 是一个更好的建模方式:
id | name |
---|---|
1 | foo |
id | entity_id | attr_name | attr_value |
---|---|---|---|
1 | 1 | attr_0 | 1 |
2 | 1 | attr_1 | 33 |
… | … | … | … |
n | 1 | attr_n | any |
这种模型下, ORM 层面我们考虑封装一个对操作更友好的上层操作接口, 比如:
1 | obj = Entity() |
实现上, 就是把对象的方法, 包装成 SQLAlchemy
的 ORM
中的对应的关系操作.
1 | class BaseModel(declarative_base()): |
实现上就两点:
_attributes
关系中, 指定 collection_class
, 于是就可以得到一个像 dict
的属性对象了.association_proxy
从 dict
的属性对象中只抽出我们关心的 value
属性值.
这个场景中, 还可以再进一步, 在 Entity
类上实现 dict
的一些方法, 直接操作其 attributes
属性, association_proxy
就直接返回 Entity
的实例, 这样代码可以变成这样:
1 | entity = Entity(name=u'ABC') |
1 | from sqlalchemy import create_engine |
engine 的定义包含了三部分的内容:
所谓的数据库类型即是MYSQL
, Postgresql
, SQLite
这些不同的数据库.
一般创建 engine 是使用create_engine
方法:
1 | engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/mydatabase') |
对于这个字符串, SQLAlchemy 提供了工具可用于处理它:
1 | # -*- coding: utf-8 -*- |
create_engine
函数有很多的控制参数, 这个后面再详细说.
create_engine
的调用, 实际上会变成strategy.create
的调用. 而strategy
就是engine
的实现细节. strategy
可以在create_engine
调用时通过strategy
参数指定, 目前官方的支持有三种:
mock
这个实现, 会把所有的 SQL
语句的执行交给指定的函数来做, 这个函数是由create_engine
的 executor
参数指定:
1 | def f(sql, *args, **kargs): |
各数据库的实现在 SQLAlchemy 中分成了两个部分, 一是数据库的类型, 二是具体数据库中适配的客户端实现. 比如对于 Postgresql 的访问, 可以使用psycopg2
, 也可以使用pg8000
:
1 | s = 'postgresql+psycopg2://test@localhost:5432/bbcustom' |
具体的适配工作, 是需要在代码中实现一个 Dialect 类来完成的. 官方的实现在 dialects 目录下.
获取具体的 Dialect 的行为, 则是前面提到的URL
对象的get_dialect
方法.create_engine
时你单传一个字符串,SQLAlchemy
自己也会使用make_url
得到一个URL
的实例).
SQLAlchemy 支持连接池, 在create_engine
时添加相关参数即可使用.
连接池效果:
1 | # -*- coding: utf-8 -*- |
连接池的实现, 在create_engine
调用时也可以指定:
1 | from sqlalchemy.pool import QueuePool |
还有:
1 | from sqlalchemy.pool import NullPool |
或者仅仅是获取连接的方法:
1 | import sqlalchemy.pool as pool |
连接池可以被单独使用:
1 | import sqlalchemy.pool as pool |
连接池可以被多个 engine 共享使用:
1 | e = create_engine('postgresql://', pool=mypool) |
之前代码里面的contact是可以重复的,现在要将其改成unique的,改代码容易,但是还要兼容之前的数据,就要想办法将之前重复的给改掉
方法1: 手动写SQL,在执行到具体的migrations时先执行SQL,但是这个不太统一,另外推代码时容易忘记。
方法2: 框架用的人多就是好,不要重复造轮子,如下:
1 |
|
来到公司已经半年了,经历了蛮多的事情,慢慢的从陌生到熟悉到被信任,从部分开发到主力开发,这个过程是非常艰难但又非常开心但又非常有责任的。从与项目经理交流获取业务流程、细节到脑中大致出现业务模型然后到数据库的表结构设计到提供api到测试到文档的编写,每一步都亲力亲为,很多时候又会特地放慢脚步,生怕出现哪个地方没有想到,哪个地方设计的不合理。程序写完并且走完单元测试后,还要写文档给客户端以及Web端,要有分组,哪些给客户端的,哪些给Web端的,哪些接口应该放在一起,怎么将接口排序,哪些接口需不需要验证,需不需要授权,参数怎么传,格式,校验……
最后主要还要在客户端以及Web端看不太明白时还要过去跟他解释、示范,整个过程都是非常的费力以及也是被逐渐熟悉并信任的过程。如果客户端或者web端说某个接口是不是有问题或者测试说这里表现的有些问题,自己还有点心惊胆战以及半信半疑,当发现是他们没有填写对或者没读懂文档或者其它问题导致时,这个过程就慢慢的被人所信任,一旦出现了问题,你的能力就会被怀疑,也许这个责任是比较有压力的,也是感受的比较深的。
目前的我觉得后端担负的责任以及压力还是蛮大的,所有的上层建筑均踩在后端的基础上,想起之前公司总监说后端最终展示出来的可能只是冰山一角。也许这句话有些夸大,但是慢慢的我感觉是对的,所有人都在等你接口,都在等你的实现,虽然我很喜欢后端,但是这个有些倾斜的天平让我觉得有些不适应。
但是我还是很喜欢这个角色,也很喜欢接受更多的挑战,不仅仅是技术方面的,还有在整个团队中的挑战,以前觉得接触更多新的技术可以让自己觉得更具有挑战性,现在有些觉得把事情做好并被认可可能更具备挑战性。我觉得我可以做的更好,也可以担负起更多的责任,慢慢努力,慢慢走!
根据不同的tag进行定位,例如:
1 | { |
上面表示: 发送消息给农技员ID为12、过程为67、环境为test。又由于多台设备可以指定相同的tag,从而单条推送可以推送给多台设备。所以此处的组播意思可能就变了,根据不同的tag组合定位到不同的设备个、群体,实现组播发送,此处tag为app端设置。
官方文档限制每分钟只能发送5条消息,所以后端维持一个队列A
以及计时器
,进行分批发送,保证消息发送出去。
此队列实现思想:
此计时器实现思想:
201712100304
,利用redis incr进行操作此key,如果大于5,则表示此分钟已经发送满,则继续轮训至下分钟进行发送队列B
,实现原子性操作,此处只能表示此任务已经被执行了,但是不能代表执行成功,此处可参考错误
对于错误1,理论应再次推入队列A
,但此处不考虑。
对于错误2,除了应用次数限制错误,其余错误可以避免。
此处队列与存储均使用redis进行实现,所以理论上只要redis服务不停止,服务状态与结果均可以持久化存储,又由于推送非持久化过程,所以此处暂时满足。
后端维持一个定时任务,到达时间后,会将消息推送给队列A,等待发送。
此处可以动态增、删任务。
将此消息推到队首/尾,等待发送。
转战友盟,此片结束。
嗯嗯,为什么会有这篇文章??
知道当你写代码的时候前端让你拉代码的痛苦么~~,没有运维我来上,手动多了就更😡了,所以,你懂的。。
1 | ## 搭建 |
1 |
|
invoke \
–> proto
–> protos
–> hello.proto
1 | python -m grpc_tools.protoc -I proto --python_out=. --grpc_python_out=. proto/protos/hello.proto |
最后的目录结构:
invoke
–> proto
–> protos
–> hello.proto
–> protos
–> hello_pb2.py
–> hello_pb2_grpc.py
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true