Giter Site home page Giter Site logo

julien6387 / supvisors Goto Github PK

View Code? Open in Web Editor NEW
85.0 4.0 14.0 43.4 MB

Supvisors: A Control System for Distributed Applications

Home Page: http://supvisors.readthedocs.io

License: Apache License 2.0

Python 89.38% Shell 0.78% CSS 0.62% HTML 1.78% Java 7.44%
supervision distributed-systems application supervisor orchestration

supvisors's People

Contributors

julien6387 avatar tiagocoutinho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

supvisors's Issues

can't start supervisord

ubuntu 14.04.1
pip install supvisors[all]
Requirement already satisfied: supvisors[all] in /usr/local/lib/python2.7/dist-packages
Requirement already satisfied: supervisor>=3.3.0 in /usr/local/lib/python2.7/dist-packages (from supvisors[all])
Requirement already satisfied: pyzmq>=15.2.0 in /usr/local/lib/python2.7/dist-packages (from supvisors[all])
Requirement already satisfied: netifaces>=0.10.4 in /usr/local/lib/python2.7/dist-packages (from supvisors[all])
Requirement already satisfied: psutil>=4.3.0 in /usr/local/lib/python2.7/dist-packages (from supvisors[all])
Requirement already satisfied: matplotlib>=1.5.2 in /usr/local/lib/python2.7/dist-packages (from supvisors[all])
Requirement already satisfied: lxml>=3.2.1 in /usr/local/lib/python2.7/dist-packages (from supvisors[all])
Requirement already satisfied: meld3>=0.6.5 in /usr/local/lib/python2.7/dist-packages (from supervisor>=3.3.0->supvisors[all])
Requirement already satisfied: numpy>=1.7.1 in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: six>=1.10 in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: pytz in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: subprocess32 in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: python-dateutil>=2.0 in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: backports.functools-lru-cache in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python2.7/dist-packages (from matplotlib>=1.5.2->supvisors[all])

use the config of example,

and can't startup the supervisord.But it can run when I remove the supvisors configs.
supvisors log:
2018-01-05 17:40:24,743 INFO Expected addresses: ['119.23.xxx.xxx']
2018-01-05 17:40:24,744 INFO Local addresses: ['cluster-1', u'10.27.xxx.xxx', u'119.23.xxx.xxx'] - Local address: 119.23.xxx.xxx
2018-01-05 17:40:24,752 INFO using lxml.etree parser
2018-01-05 17:40:24,752 WARN cannot parse rules file: None
2018-01-05 17:40:24,780 INFO Expected addresses: ['119.23.xxx.xxx']
2018-01-05 17:40:24,780 INFO Local addresses: ['cluster-1', u'10.27.xxx.xxx', u'119.23.xxx.xxxx'] - Local address: 119.23.xxx.xxx
2018-01-05 17:40:24,780 INFO using lxml.etree parser
2018-01-05 17:40:24,780 WARN cannot parse rules file: None
2018-01-05 17:40:24,783 INFO local supervisord is RUNNING
2018-01-05 17:40:24,783 WARN Server running without any HTTP authentication checking
2018-01-05 17:40:24,783 INFO binding local Supvisors EventPublisher to tcp://127.0.0.1:60002
2018-01-05 17:40:24,783 INFO binding InternalEventPublisher to tcp://*:60001
2018-01-05 17:40:24,783 INFO binding RequestPuller to inproc://supvisors

supervisord.log
2018-01-05 17:40:24,737 CRIT Supervisor running as root (no user in config file)
2018-01-05 17:40:24,738 INFO RPC interface 'supervisor' initialized
2018-01-05 17:40:24,773 INFO RPC interface 'supvisors' initialized
2018-01-05 17:40:24,773 CRIT Server 'inet_http_server' running without any HTTP authentication checking
2018-01-05 17:40:24,773 INFO RPC interface 'supervisor' initialized
2018-01-05 17:40:24,781 INFO RPC interface 'supvisors' initialized
2018-01-05 17:40:24,781 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2018-01-05 17:40:24,782 INFO daemonizing the supervisord process
2018-01-05 17:40:24,783 INFO supervisord started with pid 19830

Collate CPU and mem usage over process group

When

stopasgroup=true
killasgroup=true

are set, the user probably want to see the CPU/mem utilization over the group, and not just the parent process.

Would this be possible to add?

restart: code=101, text="BAD_SUPVISORS_STATE: Supvisors (state=INITIALIZATION)

Recently we've tried to implement 'supvisors' into our supervisord for easier management using the dashboard, we've encountered an error where the it keep stuck in 'INITIALIZATION' state. We are new to UNIX OS as well as the supervisor, hope that you can help us resolve this issue. Here is error we keep receiving upon re-synchronyzation.

2022-09-19 16:15:45,356;CRIT;SupervisorListener.on_tick: Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/supvisors/listener.py", line 265, in on_tick
self.pusher.send_tick_event(payload)
AttributeError: 'NoneType' object has no attribute 'send_tick_event'

2022-09-19 16:15:46,361;INFO;SupvisorsInstanceStatus.state: Supvisors=htv-virtual-machine is CHECKING
2022-09-19 16:15:46,362;WARN;InitializationState.next: synchro timed out
2022-09-19 16:15:46,362;INFO;SupvisorsInstanceStatus.state: Supvisors=htv-virtual-machine is CHECKING
2022-09-19 16:15:46,362;CRIT;SupervisorListener.on_remote_event: Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/supvisors/listener.py", line 285, in on_remote_event
self.unstack_event(event.data)
File "/usr/local/lib/python3.10/dist-packages/supvisors/listener.py", line 297, in unstack_event
self.supvisors.fsm.on_tick_event(event_identifier, event_data)
File "/usr/local/lib/python3.10/dist-packages/supvisors/statemachine.py", line 493, in on_tick_event
self.context.on_tick_event(identifier, event)
File "/usr/local/lib/python3.10/dist-packages/supvisors/context.py", line 429, in on_tick_event
self.check_instance(status)
File "/usr/local/lib/python3.10/dist-packages/supvisors/context.py", line 632, in check_instance
self.supvisors.zmq.pusher.send_check_instance(status.identifier)
AttributeError: 'NoneType' object has no attribute 'pusher'

2022-09-19 16:15:46,364;WARN;Context.on_authorization: failed to get auth status from Supvisors=htv-virtual-machine
2022-09-19 16:15:46,364;CRIT;Context.invalid: local Supvisors instance is either SILENT or inconsistent
2022-09-19 16:15:46,364;INFO;SupvisorsInstanceStatus.state: Supvisors=htv-virtual-machine is SILENT
2022-09-19 16:15:46,364;WARN;Context.on_authorization: failed to get auth status from Supvisors=htv-virtual-machine
2022-09-19 16:15:46,364;CRIT;Context.invalid: local Supvisors instance is either SILENT or inconsistent
2022-09-19 16:15:46,364;INFO;SupvisorsInstanceStatus.state: Supvisors=htv-virtual-machine is SILENT
2022-09-19 16:15:46,364;CRIT;SupervisorListener.on_remote_event: Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/supvisors/listener.py", line 283, in on_remote_event
self.authorization(event.data)
File "/usr/local/lib/python3.10/dist-packages/supvisors/listener.py", line 338, in authorization
self.supvisors.fsm.on_authorization(identifier, authorized, master_identifier)
File "/usr/local/lib/python3.10/dist-packages/supvisors/statemachine.py", line 604, in on_authorization
if self.context.on_authorization(identifier, authorized):
File "/usr/local/lib/python3.10/dist-packages/supvisors/context.py", line 380, in on_authorization
self.invalid(status)
File "/usr/local/lib/python3.10/dist-packages/supvisors/context.py", line 198, in invalid
self.supvisors.zmq.publisher.send_instance_status(status.serial())
AttributeError: 'NoneType' object has no attribute 'publisher'

Error: supvisors.plugin:make_supvisors_rpcinterface cannot be resolved within [rpcinterface:supvisors]

hi:
i'm running supvisors on Centos7.0, but that error has happened, and can u help
me troubleshoot this error?

##supervisord.conf:

[inet_http_server] ; inet (TCP) server disabled by default
port=:10000 ; (ip_address:port specifier, :port for all iface)
;username=football ; (default is no username (open server))
;password=k
@hu19k8aQ1 ; (default is no password (open server))

[supervisord]
logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=500MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=warn ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=http://localhost:10000 ; use an http:// url to specify an inet socket
[include]
files = /etc/supervisor/conf.d/*.conf
[supvisors]
address_list=47.92.152.87
deployment_file=/etc/supervisors/application.xml
auto_fence=false
internal_port=10001
event_port=10002
synchro_timeout=20
deployment_strategy=LESS_LOADED
conciliation_strategy=INFANTICIDE
stats_periods=5,60,600
stats_histo=100
logfile=/etc/supervisors/supvisors.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
[rpcinterface:supvisors]
supervisor.rpcinterface_factory = supvisors.plugin:make_supvisors_rpcinterface
[ctlplugin:supvisors]
supervisor.ctl_factory = supvisors.supvisorsctl:make_supvisors_controller_plugin

applicaton.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
<!-- lunar_spider application -->
<application name="lunar_spider">
<start_sequence>3</start_sequence>
<stop_sequence>2</stop_sequence>
<program name="scrape_api_server">
<addresses>*
<start_sequence>1</start_sequence>
<stop_sequence>2</stop_sequence>
<required>true
<expected_loading>5</expected_loading>
</program>
</application>
</root>

thx!

complement the definition of '#'

in pattern rules, the definition of '#' applies to the whole list of nodes that are declared in the supvisors section of the supervisor configuration file.
it could be considered to apply '#'to a subset of these nodes by declaring something like:
#, subnode1, subnode2

when using username and passwd in inet_http_server, can't see the host page

2018-01-05 23:27:30,995 ERRO Web interface error:Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/supervisor/web.py", line 45, in more
response = self.callback()
File "/usr/local/lib/python2.7/dist-packages/supervisor/web.py", line 162, in call
body = self.render()
File "/usr/local/lib/python2.7/dist-packages/supvisors/viewprocaddress.py", line 47, in render
return ViewHandler.render(self)
File "/usr/local/lib/python2.7/dist-packages/supvisors/viewhandler.py", line 74, in render
self.write_contents(root)
File "/usr/local/lib/python2.7/dist-packages/supvisors/viewprocaddress.py", line 75, in write_contents
self.write_process_table(root)
File "/usr/local/lib/python2.7/dist-packages/supvisors/viewprocaddress.py", line 93, in write_process_table
for info in self.info_source.supervisor_rpc_interface.getAllProcessInfo():
File "/usr/local/lib/python2.7/dist-packages/supvisors/infosource.py", line 48, in supervisor_rpc_interface
self._supervisor_rpc_interface = self.httpserver.handlers[0].rpcinterface.supervisor
AttributeError: supervisor_auth_handler instance has no attribute 'rpcinterface'

unknown error (try "tail xxx")

when a FATAL state is forced by supvisors, it is displayed differently in procaddress and application pages.
the procaddress seems correct (e.g. 'no resource available'), whereas the application page displays 'unknown error (try "tail xxx")'

risk of deadlock at startup

when receiving the first event from B, the event is posted through a RemoteCommEvent to the Supervisor main thread.
Then A performs a XML-RPC to B in order to know if A is considered ISOLATED by B.
The use of the RemoteCommEvent blocks any RPC coming to A as long as it did not receive a response from B.
with bad luck, B is doing the same with A at the same time and A and B block themselves.

stop_sequence not implemented for an applicative process

idea is to follow an order when stopping the processes of an application.
the stop_sequence element is already parsed and stored in rules.
a value of 0 stands for an immediate stop, then stop processes of group 1, 2, etc.

fix incorrect use of PyZMQ

in Supvisors, ZMQ sockets are not used by multiple threads.
however, they are all created in the Supervisor thread, which is not the correct way to do it.

Recommendation is to create / use / destroy the ZMQ socket in the same thread.

that would explain random crashes like this one:
Bad file descriptor (src/epoll.cpp:119)
Bad file descriptor (src/tcp.cpp)

re-design the 'required' option

push the definition at application level
idea is to declare at once :

  • the programs that are always required
  • the programs that can be optional if another one is running

something like:

<all_of>program_x, program_y, program_z</all_of>
<one_of>program_a, program_b</one_of>
<one_of>program_00, program_01, program_02</one_of>

double master

simple scenario:
start node1, node2, node3 => node1 is the master, as seen by nodes 2 and 3
stop node1 => node2 becomes master, as seen by node3
restart node1 => node1 declares itself as a master. node2 still the master, as seen by node3
restart node3 => node1 master, node2 master, node3 sees node1 as master

when a new node becomes active, it is needed to come back to INITIALIZATION state.

Multiple docker images with supvisor servers in them usage case

Hello,

Thanks for this well documented project!

I'm considering using supvisors as a unified view of a set of Docker containers with supervisor servers inside of them. In my use case, I have a few (currently 3) docker containers where each one of them runs a series of processes. These containers are running in the same machine and they use the host network stack (due to internal random port usage dependencies).

I was trying to do a simple test where I am running a supervisor + supvisor on the host (with the aim that this one would have just a couple of jobs to start the docker containers) and a supervisor + supvisor in a container with a group of processes. I expected to be able to see them in the web ui.

However, I'm finding myself running into socket already in use errors (zmq.error.ZMQError: Address already in use).

I wonder if I'm just trying to do something that is impossible or I'm just getting the config wrong.

I have/want:

Host OS                  --> supervisor + supvisors with default config
                                                   |__ run docker image(s) start script
Docker container 1 --> supervisor + supvisors with default config
                                                   |__ run process(es) inside of container
Docker container 2 ...
Docker container N 

I see in your example scenarios that the different supervisor+supvisors config are executed by ssh-ing into another machine and running supervisor. Being in a different machine I understand that they can re-use ports. If I try to use another port, it runs, but then, I do not know how to tell... the web ui part? to find the additional servers?

I'm still testing, but I thought I'd post already in case someone can give me pointers. Thanks for any help you can provide!

the netifaces dependency could be made optional

it is only used in supvisors.address_mapper, in ipv4 method

if optional (change doc in README and introduction), the local address would be restricted to the host name (host node from a Supervisor point of view), which could be acceptable if documented

=> move the import in ipv4 and deal with ImportError
=> update documentation about address_list configuration and places where 'IP address' may be referred to.
=> update setup.py dependencies

Supervisor momentary freezes and causes Supvisors to desync

The Supvisors TICK shared across all nodes is driven by Supervisor TICK_5.
On a special event (suspected to be a HTTP issue when requesting a refresh on the web ui), Supervisor freezes momentarily and the Supervisor TICK_5 is deferred - sometimes more than 30s. This causes Supvisors to believe that the Supervisor instance has been stopped on the related node.
Supvisors needs a more reliable source for its own TICK. Perhaps it should be generated from its own thread.

Multiple docker images with supervisord servers+supvisors in them usage case - without sync between instances

Hello

Of course thanks for this project

I have another case similar to #99, but I want to run in
separate docker supervisor+supvisors (need update_numprocs feature) + workers managed by supvisors of course

I wated to run 3 or 4 containers based on one universal image with entrypoint-app.sh (simple dispatch supervisord.conf depends on env) - I have similar solution but only with supervisord and static config (with static numprocs=x values)

Is it possible to run supervisord + supvisors rpc api without all that stuff connected with statistic sync etc? because my example log looks like below:

INFO Set uid to user 0 succeeded
 INFO RPC interface 'supervisor' initialized
WARN;SupervisorData.read_disabilities: no persistence for program disabilities
INFO;SupvisorsMapper.configure: identifiers=['server_1']
INFO;SupvisorsMapper.find_local_identifier: local_identifier=server_1
INFO;SupvisorsMapper.configure: core_identifiers=['server_1']
WARN;Supvisors: cannot parse rules files: None - 'NoneType' object is not iterable
INFO;RPCInterface: using Supvisors=0.15 Supervisor=4.2.4
INFO;RPC interface 'supvisors' initialized
CRIT;Server 'inet_http_server' running without any HTTP authentication checking
INFO;RPC interface 'supervisor' initialized
WARN;SupervisorData.read_disabilities: no persistence for program disabilities
INFO;SupvisorsMapper.configure: identifiers=['server_1']
INFO;SupvisorsMapper.find_local_identifier: local_identifier=server_1
INFO;SupvisorsMapper.configure: core_identifiers=['server_1']
WARN;Supvisors: cannot parse rules files: None - 'NoneType' object is not iterable
INFO;RPCInterface: using Supvisors=0.15 Supervisor=4.2.4
INFO;RPC interface 'supvisors' initialized
CRIT;Server 'unix_http_server' running without any HTTP authentication checking
INFO;supervisord started with pid 1
INFO;SupervisorListener.on_running: local supervisord is RUNNING
INFO;FiniteStateMachine.set_state: Supvisors in INITIALIZATION
INFO;Context.master_identifier: 
INFO;SupervisorListener.on_running: local supervisord is RUNNING
CRIT;PublisherServer._bind: failed to bind the Supvisors publisher on port 61001
INFO;FiniteStateMachine.set_state: Supvisors in INITIALIZATION
INFO;Context.master_identifier: 
INFO;SupvisorsInstanceStatus.state: Supvisors=server_1 is CHECKING
INFO;SupvisorsInstanceStatus.state: Supvisors=server_1 is CHECKING
WARN;Context.on_authorization: failed to get auth status from Supvisors=server_1
CRIT;Context.invalid: local Supvisors instance is either SILENT or inconsistent
INFO;SupvisorsInstanceStatus.state: Supvisors=server_1 is SILENT

I dont want in my logs stuff like:

CRIT;PublisherServer._bind: failed to bind the Supvisors publisher on port xxxxx
Context.invalid: local Supvisors instance is either SILENT or inconsistent

is it possible , or maybe need some futuer development?
Thanks for any help you can provide!

ps. of course I can ignore content of logs (and run containers without looking on logs) but, maybe it is possible to do that in the right way :)

synchronize transition to OPERATION

when leaving the INITIALIZATION state, only the Supvisors master stays in DEPLOYMENT state. other instances move quickly to OPERATION. OPERATION state should be reached for all instances at the same time.

aborted SHUTTING_DOWN

very unlikely in normal operation but possible anyway .
if supvisors sshutdown or sreload is requested from node X and immediately after, a supervisor shutdown is sent to node X, then the stopping sequence of the applications is aborted and the initial shutdown/restart cannot be completed.
that leads the other nodes to eventually re-sync but the situation is a bit strange as there has been some applications properly stopped and there's nothing to be repaired.
this is not blocking but definitely not desired.

easy scenario to repeat:
supervisorctl sshutdown ; supervisorctl shutdown

ERROR (BAD_SUPVISORS_STATE: Supvisors (state=INITIALIZATION) not in state ['OPERATION'] to perform request)

Installed the plugin following the docs and the example conf.
All works well, supvisorsctl command works, but if I try to do anything specific to supvisors plugin, for example to update_numprocs it throws the above error

The supervisord logs the following:

2022-05-25 16:02:38,530;INFO;SupvisorsInstanceStatus.state: Supvisors=test-server.addpipe.com is CHECKING
2022-05-25 16:02:38,530;WARN;InitializationState.next: synchro timed out
2022-05-25 16:02:38,531;INFO;SupvisorsInstanceStatus.state: Supvisors=test-server.addpipe.com is CHECKING
2022-05-25 16:02:38,531;CRIT;SupervisorListener.on_remote_event: Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/supvisors-0.14-py3.6.egg/supvisors/listener.py", line 285, in on_remote_event
    self.unstack_event(event.data)
  File "/usr/local/lib/python3.6/site-packages/supvisors-0.14-py3.6.egg/supvisors/listener.py", line 297, in unstack_event
    self.supvisors.fsm.on_tick_event(event_identifier, event_data)
  File "/usr/local/lib/python3.6/site-packages/supvisors-0.14-py3.6.egg/supvisors/statemachine.py", line 493, in on_tick_event
    self.context.on_tick_event(identifier, event)
  File "/usr/local/lib/python3.6/site-packages/supvisors-0.14-py3.6.egg/supvisors/context.py", line 429, in on_tick_event
    self.check_instance(status)
  File "/usr/local/lib/python3.6/site-packages/supvisors-0.14-py3.6.egg/supvisors/context.py", line 632, in check_instance
    self.supvisors.zmq.pusher.send_check_instance(status.identifier)
AttributeError: 'NoneType' object has no attribute 'pusher'

add the possibility to overwrite a program model

in program rules, it is stated that "This use of the reference element is exclusive to the use of the following elements."
it may be interesting to consider that it is not exclusive so that the following elements could supersede the information defaulted in the program model

rare and random freeze on restart

issue title renamed as it was a consequence of another problem

it may happen that the main loop does not stop on restart
seems to be a problem in the pool

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.